init() is called, mcp-tap monkey-patches each supported SDK. If a library isn’t installed, its patch is silently skipped. Patches never raise exceptions or affect application behavior.
Supported SDKs
| SDK | TypeScript | Python | What’s patched |
|---|---|---|---|
| Anthropic | @anthropic-ai/sdk | anthropic | Messages.create (sync + async in Python) |
| OpenAI | openai | openai | Chat.Completions.create (sync + async in Python) |
| MCP Client | @modelcontextprotocol/sdk | mcp | Client.callTool / ClientSession.call_tool |
| Composio | composio-core | composio | ComposioToolSet.executeAction / execute_action |
| HTTP (catch-all) | globalThis.fetch | httpx | Requests to known AI API hosts |
What gets captured
For LLM requests (Anthropic, OpenAI, HTTP), mcp-tap emits anllm_request parent event with:
- Model name, system prompt, request messages, response content
- Token usage (input/output/cache tokens)
- Thinking/reasoning blocks (if present)
- Stop reason
- Latency
tool_call event is emitted with the tool name and input arguments, linked to the parent via parent_event_id.
For MCP and Composio calls, a tool_call event is emitted with tool name, inputs, output, error (if any), and latency.
Individual patch functions
Each patch can be applied independently if you don’t wantinit() to patch everything:
Double-counting prevention
When both an SDK patch and the HTTP patch are active, the SDK patch marks a flag (_inSdkPatch in TypeScript, mark_sdk_patch() in Python) during execution. The HTTP patch checks this flag and skips interception when it’s set, preventing the same call from being logged twice.