Connect your client¶
Every client needs the same two things: the URL https://trru.atapinar.com/mcp and the header Authorization: Bearer trru_YOUR_KEY. The server has no OAuth sign-in, so pick the client option that sends a fixed header. Use a data key unless you need query_sql or company contact details; see key scopes.
Keep the key private
The key sits in a config file or in the client's connector store. Do not commit it to a repository. Keys cannot be recovered, only replaced, so if one leaks, ask for a new one and remove the old connection.
Claude Code¶
claude mcp add --transport http trru https://trru.atapinar.com/mcp \
--header "Authorization: Bearer trru_YOUR_KEY"
--transport and --header also accept the short forms -t and -H. Check that it connected:
claude mcp list # trru: https://trru.atapinar.com/mcp (HTTP) - ✔ Connected
claude mcp get trru # scope, status, URL and a masked header
Inside a Claude Code session, /mcp shows the server and its tools, and offers Reconnect.
Where the entry is stored depends on --scope (short form -s):
| Scope | Flag | Visible to | Stored in |
|---|---|---|---|
local (default) |
none | You, in the current project only | ~/.claude.json |
project |
--scope project |
Everyone who uses the repository | .mcp.json in the project root |
user |
--scope user |
You, in every project | ~/.claude.json |
claude mcp add --transport http trru --scope user https://trru.atapinar.com/mcp \
--header "Authorization: Bearer trru_YOUR_KEY"
For project scope do not write the key into the file you commit. Claude Code expands environment variables in .mcp.json headers, so each person keeps the key in their own shell:
{
"mcpServers": {
"trru": {
"type": "http",
"url": "https://trru.atapinar.com/mcp",
"headers": {"Authorization": "Bearer ${TRRU_KEY}"}
}
}
}
Remove the server, or replace the key, with:
Then run the add command again with the new key. Claude Code asks for approval before using a project-scoped server for the first time.
claude.ai and Claude Desktop (custom connector)¶
Claude's custom connectors run from Anthropic's cloud, so the server must be reachable from the internet (it is). The steps below follow Anthropic's page Add a connector that isn't in the directory; the interface changes from time to time, so compare with that page if a label differs.
- Open Customize > Connectors (Team and Enterprise Owners: Organization settings > Connectors).
- Select Add, hover Custom, and select Web (if asked for a connector type).
- Enter a name (for example
TRRU) and the MCP server URLhttps://trru.atapinar.com/mcp. - For Authentication, choose No sign in (the server has no OAuth flow).
- Under Request headers (in the one-screen dialog, under Advanced) add a header named
authorizationwith the valueBearer trru_YOUR_KEY. Claude sends the value exactly as entered and adds no scheme, so the wordBearerand the space must be part of the value. - Click Add. In a chat, open the + menu, select Connectors, and turn the connector on for that conversation.
The request-header option may not be available to you
Anthropic describes request headers as a beta feature "available to a limited set of organizations", and says: "If you don't see the Request headers section in the Add custom connector dialog, your organization doesn't have access yet." Its authentication page lists the fixed-credential type as "Beta, for a limited set of organizations". If the section is missing, use Claude Code or the mcp-remote bridge below. Anthropic also notes that authentication settings cannot be changed after a connector is added: to rotate a key, remove the connector and add it again.
Claude Desktop with the mcp-remote bridge¶
Claude Desktop can also start a local program that speaks stdio. mcp-remote is a small Node package that turns a remote MCP server into such a program and can add custom headers. It needs Node.js (for npx).
Open the config file (Settings > Developer > Edit Config), which lives at ~/Library/Application Support/Claude/claude_desktop_config.json on macOS and %APPDATA%\Claude\claude_desktop_config.json on Windows, and add:
{
"mcpServers": {
"trru": {
"command": "npx",
"args": [
"mcp-remote",
"https://trru.atapinar.com/mcp",
"--header",
"Authorization:${AUTH_HEADER}",
"--transport",
"http-only"
],
"env": {
"AUTH_HEADER": "Bearer trru_YOUR_KEY"
}
}
}
}
The header is written without a space after the colon and the real value is passed through env. This is the workaround the mcp-remote README gives for clients that mangle spaces inside args (Claude Desktop on Windows is named there); the README also shows the plain form "--header", "Authorization: Bearer trru_YOUR_KEY", but then the key is visible in the process list of your machine. Restart Claude Desktop after editing the file. --transport http-only makes the bridge use the streamable HTTP transport this server speaks, instead of trying SSE.
Hermes¶
Add the server to ~/.hermes/config.yaml under mcp_servers:
mcp_servers:
trru:
url: https://trru.atapinar.com/mcp
headers:
Authorization: "Bearer trru_YOUR_KEY"
connect_timeout: 60
timeout: 120
Then reload without restarting: type /reload-mcp in a running session, or start a new session. Tools appear with the prefix mcp_trru_, for example mcp_trru_product_check. Check the connection from a shell with hermes mcp list and hermes mcp test trru. timeout is the per-tool-call limit in seconds; connect_timeout covers the first connection and tool discovery.
Other MCP clients (generic JSON)¶
Most desktop and IDE clients (Cursor, Windsurf, VS Code and similar) read a JSON file with a server map. The shape is usually:
{
"mcpServers": {
"trru": {
"url": "https://trru.atapinar.com/mcp",
"headers": {"Authorization": "Bearer trru_YOUR_KEY"}
}
}
}
Some clients want an explicit transport field, spelled "type": "http", "type": "streamable-http" or "transport": "streamableHttp"; check your client's documentation for the exact key. If a client only supports local (stdio) servers, use the mcp-remote bridge from the section above with the same arguments.
Python (official mcp package)¶
This script lists the tools and calls latest with the official Python SDK over streamable HTTP. It was run against mcp 2.3.0 (pip install mcp, Python 3.10 or newer) with a data key in TRRU_KEY:
import asyncio
import json
import os
from mcp import ClientSession
from mcp.client.streamable_http import create_mcp_http_client, streamable_http_client
URL = "https://trru.atapinar.com/mcp"
HEADERS = {"Authorization": f"Bearer {os.environ['TRRU_KEY']}"}
async def main() -> None:
http = create_mcp_http_client(headers=HEADERS)
async with http, streamable_http_client(URL, http_client=http) as (read, write):
async with ClientSession(read, write) as session:
await session.initialize()
tools = await session.list_tools()
print(len(tools.tools), "tools:", ", ".join(t.name for t in tools.tools))
result = await session.call_tool("latest", {"series_ids": ["ru.key_rate"]})
payload = json.loads(result.content[0].text) # tool output is a JSON string
row = payload["rows"][0]
print(row["series_id"], row["value"], row["unit"], "as_of", row["as_of"])
print("sources:", payload["sources"])
asyncio.run(main())
Output:
17 tools: list_series, latest, get_series, describe_schema, check_sanctions, check_hs_code, upcoming, search_docs, border_arrivals, search_companies, get_company, check_eu_restriction, product_check, source_freshness, changes_since, search_news, latest_news
ru.key_rate 14.0 % as_of 2026-11-13
sources: [{'source_id': 'cbr', 'fetched_at': '2026-11-13T17:30:30.332163+00:00', 'as_of': '2026-11-13'}]
Headers go on the HTTP client that you pass to streamable_http_client; the transport itself takes only the URL. The SDK's API has changed between major versions (older 1.x releases take headers= directly in a differently named function), so check pip show mcp and the SDK documentation if the import fails. If you only need the data, the REST API with requests is simpler; see the code examples.
Troubleshooting¶
| Symptom | Cause | Fix |
|---|---|---|
401 with {"error": {"code": "unauthorized", ...}} and WWW-Authenticate: Bearer |
Header missing, key wrong, or key revoked. Claude Code reports "Server rejected the configured Authorization header (HTTP 401)" | Check the header is exactly Authorization: Bearer trru_... (the word Bearer, one space, the key, no quotes or line break). Test with curl as in the overview. Ask for a new key if it was revoked |
403 forbidden |
The key lacks the data scope |
Use a key with scope data (see authentication) |
405 method_not_allowed on GET or DELETE |
Expected: /mcp accepts only POST (stateless, no event stream, no session to close). Clients that probe with GET should carry on with POST |
Nothing to fix. If a client stops after this answer, it needs the streamable HTTP transport rather than the older SSE transport, or use mcp-remote with --transport http-only |
406 Not Acceptable: Client must accept application/json |
The Accept header does not include application/json |
Send Accept: application/json, text/event-stream (MCP clients do this by default) |
400 Invalid Content-Type header |
Body not sent as application/json (this server answers 400, not 415) |
Send Content-Type: application/json |
400 JSON-RPC -32700 parse error |
Body is not valid JSON | Check the request body |
307 redirect from /mcp/ |
Trailing slash | Use https://trru.atapinar.com/mcp exactly |
429 rate_limited |
The key's bucket is empty (default 120 requests per minute; REST and MCP count together) | Wait Retry-After seconds. See rate limits |
| Connection timeout or no response | Network, proxy or DNS problem on your side, or the service is down | curl https://trru.atapinar.com/v1/health (no key needed) should return {"data": {"ok": true, "db": true}, ...}; 503 means the database is down. A single tool call that runs long returns a timeout error inside the result |
Unknown tool: query_sql (or another name) |
The tool is not in your scope's set (query_sql needs an admin key), or the name is misspelled |
Call tools/list and use the names it returns |
| Tool list looks old or a new tool is missing | The client cached the list from an earlier connection | Reconnect: /mcp > Reconnect in Claude Code, /reload-mcp in Hermes, toggle the connector off and on (or remove and re-add it) in Claude, restart Claude Desktop after editing its config |
Tool result is {"error": {"code": "bad_request", ...}} and isError is false |
The data layer rejected an argument | Read the message; it names the problem (for example hs6 must be exactly 6 digits) |