added context7 connector to extra tools
This commit is contained in:
@@ -247,6 +247,39 @@ Options include `-l/--location`, `-u/--units` (`m`/`u`/`M`), `-L/--lang`,
|
||||
`https://wttr.in`) and `WEATHER_TIMEOUT` (default `20`s).
|
||||
|
||||
Dependencies: `curl`, `jq` (only required for the JSON format).
|
||||
Dependencies: `curl`, `jq` (only required for the JSON format).
|
||||
|
||||
### `extras/context7`
|
||||
|
||||
A documentation lookup tool for Bantam backed by the
|
||||
[Context7 public MCP server](https://mcp.context7.com/mcp). It speaks the same
|
||||
JSON-RPC MCP protocol as `websearch` (`initialize` ->
|
||||
`notifications/initialized` -> `tools/call`) and prints the returned text.
|
||||
Context7 keeps up-to-date docs and code examples for thousands of libraries and
|
||||
exposes two tools, both wrapped here:
|
||||
|
||||
- `resolve-library-id` — maps a library name to a Context7 ID
|
||||
(`/org/project`).
|
||||
- `query-docs` — fetches documentation and code examples for a resolved ID.
|
||||
|
||||
Usage:
|
||||
|
||||
```sh
|
||||
extras/context7 resolve "React" "hooks" # list candidate library IDs
|
||||
extras/context7 query "/reactjs/react.dev" "useEffect cleanup" # fetch docs
|
||||
extras/context7 docs "Express" "middleware error handling" # resolve + query
|
||||
extras/context7 --help
|
||||
```
|
||||
|
||||
The `docs` subcommand is a convenience that resolves the library, auto-selects
|
||||
the top-ranked match, and immediately queries it (the chosen ID is printed to
|
||||
stderr so stdout stays clean for piping). Environment overrides:
|
||||
`CONTEXT7_MCP_ENDPOINT` (default `https://mcp.context7.com/mcp`) and
|
||||
`CONTEXT7_API_KEY` (optional; sent as the `X-Context7-API-Key` header for
|
||||
higher rate limits / private docs).
|
||||
|
||||
Dependencies: `curl`, `jq`.
|
||||
|
||||
|
||||
## FAQ
|
||||
|
||||
|
||||
Executable
+199
@@ -0,0 +1,199 @@
|
||||
#!/bin/sh
|
||||
# context7 - query library/framework documentation via the Context7 public
|
||||
# MCP server (https://mcp.context7.com/mcp).
|
||||
#
|
||||
# Context7 keeps up-to-date docs and code examples for thousands of libraries
|
||||
# and frameworks and exposes them through an MCP (Model Context Protocol)
|
||||
# server. This script speaks the JSON-RPC MCP protocol over HTTP:
|
||||
# 1. initialize -> obtains an Mcp-Session-Id (optional)
|
||||
# 2. notifications/initialized -> no reply
|
||||
# 3. tools/call -> runs a Context7 tool and prints text
|
||||
#
|
||||
# Context7 provides two tools:
|
||||
# * resolve-library-id maps a library name to a Context7 ID (/org/project).
|
||||
# * query-docs fetches docs + examples for a resolved library ID.
|
||||
#
|
||||
# Usage:
|
||||
# context7 resolve <libraryName> [query]
|
||||
# Search for a library and print the candidate Context7 IDs with their
|
||||
# description, snippet count, reputation and benchmark score.
|
||||
#
|
||||
# context7 query <libraryId> <query>
|
||||
# Fetch documentation for an explicit library ID (format /org/project
|
||||
# or /org/project/version). The ID usually comes from `resolve`.
|
||||
#
|
||||
# context7 docs <libraryName> <query>
|
||||
# Convenience: resolve the library, auto-pick the top-ranked match and
|
||||
# immediately query its documentation.
|
||||
#
|
||||
# context7 --help
|
||||
#
|
||||
# Environment:
|
||||
# CONTEXT7_MCP_ENDPOINT optional; default https://mcp.context7.com/mcp
|
||||
# CONTEXT7_API_KEY optional; if set, sent as the X-Context7-API-Key
|
||||
# request header (for higher rate limits / private
|
||||
# docs). No extra headers are added when unset.
|
||||
#
|
||||
# Dependencies: curl, jq.
|
||||
|
||||
set -eu
|
||||
|
||||
usage() {
|
||||
sed -n '/^# Usage:/,/^# Dependencies:/p' "$0" | sed 's/^# \{0,1\}//'
|
||||
}
|
||||
|
||||
if [ "$#" -lt 1 ]; then
|
||||
usage >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
CMD="$1"
|
||||
shift
|
||||
|
||||
case "$CMD" in
|
||||
-h|--help|help)
|
||||
usage
|
||||
exit 0
|
||||
;;
|
||||
resolve|query|docs)
|
||||
;;
|
||||
*)
|
||||
echo "context7: unknown command '$CMD' (try --help)" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
# --- Validate argument counts per command. ---
|
||||
case "$CMD" in
|
||||
resolve)
|
||||
if [ "$#" -lt 1 ]; then
|
||||
echo "context7: resolve requires <libraryName> [query]" >&2
|
||||
exit 1
|
||||
fi
|
||||
LIB_NAME="$1"
|
||||
QUERY="${2:-$1}"
|
||||
;;
|
||||
query)
|
||||
if [ "$#" -lt 2 ]; then
|
||||
echo "context7: query requires <libraryId> <query>" >&2
|
||||
exit 1
|
||||
fi
|
||||
LIB_ID="$1"
|
||||
QUERY="$2"
|
||||
;;
|
||||
docs)
|
||||
if [ "$#" -lt 2 ]; then
|
||||
echo "context7: docs requires <libraryName> <query>" >&2
|
||||
exit 1
|
||||
fi
|
||||
LIB_NAME="$1"
|
||||
QUERY="$2"
|
||||
;;
|
||||
esac
|
||||
|
||||
ENDPOINT="${CONTEXT7_MCP_ENDPOINT:-https://mcp.context7.com/mcp}"
|
||||
|
||||
# Optional auth header (single token, no spaces expected in an API key).
|
||||
AUTH_ARGS=""
|
||||
if [ -n "${CONTEXT7_API_KEY:-}" ]; then
|
||||
AUTH_ARGS="-H X-Context7-API-Key:${CONTEXT7_API_KEY}"
|
||||
fi
|
||||
|
||||
# --- MCP handshake + tool call helper. ---
|
||||
# Args: $1 = tool name, $2 = arguments JSON. Prints the parsed text content.
|
||||
mcp_call() {
|
||||
TOOL="$1"
|
||||
ARGS="$2"
|
||||
|
||||
INIT_HEADERS=$(mktemp)
|
||||
INIT_BODY=$(mktemp)
|
||||
curl -s -D "$INIT_HEADERS" -X POST "$ENDPOINT" \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "Accept: application/json, text/event-stream" \
|
||||
$AUTH_ARGS \
|
||||
-d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"context7","version":"1.0"}}}' \
|
||||
> "$INIT_BODY"
|
||||
|
||||
SID=$(grep -i '^mcp-session-id:' "$INIT_HEADERS" | tr -d '\r' | awk '{print $2}')
|
||||
|
||||
if [ -n "$SID" ]; then
|
||||
curl -s -X POST "$ENDPOINT" \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "Accept: application/json, text/event-stream" \
|
||||
-H "Mcp-Session-Id: $SID" \
|
||||
$AUTH_ARGS \
|
||||
-d '{"jsonrpc":"2.0","method":"notifications/initialized"}' > /dev/null
|
||||
SID_ARGS="-H Mcp-Session-Id:$SID"
|
||||
else
|
||||
SID_ARGS=""
|
||||
fi
|
||||
|
||||
CALL_BODY=$(mktemp)
|
||||
curl -s -X POST "$ENDPOINT" \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "Accept: application/json, text/event-stream" \
|
||||
$SID_ARGS \
|
||||
$AUTH_ARGS \
|
||||
-d "{\"jsonrpc\":\"2.0\",\"id\":2,\"method\":\"tools/call\",\"params\":{\"name\":\"$TOOL\",\"arguments\":$ARGS}}" \
|
||||
> "$CALL_BODY"
|
||||
|
||||
# Take the last "data:" SSE payload (or the whole body if plain JSON).
|
||||
DATA=$(grep -E '^data:[[:space:]]' "$CALL_BODY" | tail -n1 | sed 's/^data:[[:space:]]*//')
|
||||
if [ -z "$DATA" ]; then
|
||||
DATA=$(cat "$CALL_BODY")
|
||||
fi
|
||||
|
||||
rm -f "$INIT_HEADERS" "$INIT_BODY" "$CALL_BODY"
|
||||
|
||||
if [ -z "$DATA" ]; then
|
||||
echo "context7: no response from MCP server" >&2
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Surface protocol errors.
|
||||
ERROR_MSG=$(printf '%s' "$DATA" | jq -r 'if .error then (.error|tostring) else empty end')
|
||||
if [ -n "$ERROR_MSG" ]; then
|
||||
echo "context7 error: $ERROR_MSG" >&2
|
||||
return 1
|
||||
fi
|
||||
|
||||
printf '%s' "$DATA" | jq -r '
|
||||
(.result.content // [])
|
||||
| map(select(.type == "text"))
|
||||
| map(.text)
|
||||
| .[]
|
||||
'
|
||||
}
|
||||
|
||||
# --- Dispatch. ---
|
||||
case "$CMD" in
|
||||
resolve)
|
||||
ARGS=$(jq -n --arg n "$LIB_NAME" --arg q "$QUERY" \
|
||||
'{libraryName:$n, query:$q}')
|
||||
mcp_call "resolve-library-id" "$ARGS"
|
||||
;;
|
||||
query)
|
||||
ARGS=$(jq -n --arg id "$LIB_ID" --arg q "$QUERY" \
|
||||
'{libraryId:$id, query:$q}')
|
||||
mcp_call "query-docs" "$ARGS"
|
||||
;;
|
||||
docs)
|
||||
RARGS=$(jq -n --arg n "$LIB_NAME" --arg q "$QUERY" \
|
||||
'{libraryName:$n, query:$q}')
|
||||
RESOLVE_OUT=$(mcp_call "resolve-library-id" "$RARGS") || exit 1
|
||||
# Auto-pick the first candidate library ID from the resolve output.
|
||||
TOP_ID=$(printf '%s\n' "$RESOLVE_OUT" \
|
||||
| grep -m1 -oE '/[A-Za-z0-9_.-]+/[A-Za-z0-9_.-]+' || true)
|
||||
if [ -z "$TOP_ID" ]; then
|
||||
echo "context7: could not extract a library ID from resolve output:" >&2
|
||||
printf '%s\n' "$RESOLVE_OUT" >&2
|
||||
exit 1
|
||||
fi
|
||||
echo "context7: using library ID $TOP_ID (from resolve of '$LIB_NAME')" >&2
|
||||
QARGS=$(jq -n --arg id "$TOP_ID" --arg q "$QUERY" \
|
||||
'{libraryId:$id, query:$q}')
|
||||
mcp_call "query-docs" "$QARGS"
|
||||
;;
|
||||
esac
|
||||
|
||||
exit 0
|
||||
Reference in New Issue
Block a user