f2d

JSON-RPC Examples

Manual MCP testing with curl — initialize, discover tools, and execute searches

Overview

This page shows how to interact with f2d's MCP endpoint directly using JSON-RPC 2.0 over HTTP. This is useful for:

  • Manual testing of the MCP integration
  • Building custom MCP clients that connect to f2d
  • Debugging issues with AI assistant integrations

Most users should use Claude Desktop instead, which handles all of this automatically.

Prerequisites

  • An Access Token obtained through OAuth authentication
  • curl and jq installed

MCP clients (Claude Desktop, Claude Code) handle OAuth automatically. For manual curl testing, you'll need to obtain an Access Token through the OAuth authorization flow first.

Required Headers

Every MCP request must include these headers:

HeaderValueRequired
Content-Typeapplication/jsonYes
Acceptapplication/json, text/event-streamYes
AuthorizationBearer <your-access-token>Yes

The Accept header must include both application/json and text/event-stream. Omitting it returns a -32000 Not Acceptable error.

Initialize

Establish an MCP session. In stateless mode, each request is independent, but initialize confirms the server is available and returns its capabilities.

curl -s -X POST "<your-mcp-endpoint-url>" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -H "Authorization: Bearer <your-access-token>" \
  -d '{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "initialize",
    "params": {
      "protocolVersion": "2025-03-26",
      "capabilities": {},
      "clientInfo": {"name": "my-app", "version": "1.0.0"}
    }
  }' | jq .

Response:

{
  "result": {
    "protocolVersion": "2025-03-26",
    "capabilities": {
      "tools": { "listChanged": true }
    },
    "serverInfo": {
      "name": "f2d",
      "version": "1.0.0"
    }
  },
  "jsonrpc": "2.0",
  "id": 1
}
FieldDescription
protocolVersionMCP protocol version supported by the server
capabilities.toolsServer supports tool operations
serverInfoServer name and version

List Tools

Discover all available tools and their parameters.

curl -s -X POST "<your-mcp-endpoint-url>" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -H "Authorization: Bearer <your-access-token>" \
  -d '{"jsonrpc": "2.0", "id": 2, "method": "tools/list", "params": {}}' | jq .

The response includes full tool definitions with inputSchema (parameters) and outputSchema (response format) for each tool. See MCP Overview for a summary of available tools.

Call a Tool: search_jobs

Execute a job search.

curl -s -X POST "<your-mcp-endpoint-url>" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -H "Authorization: Bearer <your-access-token>" \
  -d '{
    "jsonrpc": "2.0",
    "id": 3,
    "method": "tools/call",
    "params": {
      "name": "search_jobs",
      "arguments": {
        "query": "machine learning engineer in Seattle",
        "top_k": 3
      }
    }
  }' | jq .

Response:

{
  "result": {
    "content": [
      {
        "type": "text",
        "text": "{\"total\": 3, \"results\": [{\"score\": 0.92, ...}]}"
      }
    ],
    "structuredContent": {
      "total": 3,
      "results": [
        {
          "score": 0.92,
          "job_title": "Machine Learning Engineer",
          "city": "Seattle",
          "company_name": "Tech Corp",
          "publish_time": "2026-03-10 13:04:19",
          "base_salary": "150000.0-200000.0 USD/YEAR",
          "job_url": "https://www.indeed.com/viewjob?jk=example"
        }
      ]
    }
  },
  "jsonrpc": "2.0",
  "id": 3
}

Understanding the Response

The response contains two representations of the same data:

FieldFormatUse case
content[]Text (stringified JSON)Backward compatibility with older MCP clients
structuredContentParsed JSON objectRecommended — use this for programmatic access

search_jobs Parameters

ParameterTypeRequiredDefaultDescription
querystringYesNatural language search query
citystringNoCity filter (exact match, case-sensitive)
countrystringNoCountry code filter (e.g. US)
sincestringNoEarliest publish date (YYYY-MM-DD)
top_kintegerNo20Number of results (1-100)
detailstringNosummarysummary or full (includes job description)

Note: The MCP parameter is query, not q (which is used in the REST API).

Call a Tool: list_cities

List available cities with job postings.

curl -s -X POST "<your-mcp-endpoint-url>" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -H "Authorization: Bearer <your-access-token>" \
  -d '{
    "jsonrpc": "2.0",
    "id": 4,
    "method": "tools/call",
    "params": {
      "name": "list_cities",
      "arguments": {}
    }
  }' | jq .

Response (in structuredContent):

{
  "total": 3,
  "cities": ["New York", "San Francisco", "Seattle"]
}

Error Responses

Missing or Invalid Token (401)

{
  "jsonrpc": "2.0",
  "error": { "code": -32600, "message": "Unauthorized" },
  "id": null
}

The response includes a WWW-Authenticate header pointing to the OAuth discovery endpoint. MCP clients use this to initiate the authorization flow automatically.

Missing Accept Header (-32000)

{
  "jsonrpc": "2.0",
  "error": {
    "code": -32000,
    "message": "Not Acceptable: Client must accept both application/json and text/event-stream"
  },
  "id": null
}

Add Accept: application/json, text/event-stream to your request headers.

Unknown Tool (-32602)

{
  "result": {
    "content": [{ "type": "text", "text": "MCP error -32602: Tool nonexistent_tool not found" }],
    "isError": true
  },
  "jsonrpc": "2.0",
  "id": 5
}

Check the tool name. Use tools/list to see available tools.

Rate Limiting (429)

HTTP 429 response with a Retry-After header. Wait the specified number of seconds before retrying.

Tips

  • Stateless mode: Each request is independent. You can call tools/call directly without calling initialize first, though following the standard flow is recommended.
  • Timeouts: Set your HTTP client timeout to at least 120 seconds. First requests may take longer due to cold start.
  • Error handling: Always check for both HTTP-level errors (401, 429) and JSON-RPC-level errors (error field in response body).

Next Steps

On this page