{"record":{"id":"d70a8453ad607032","repo":"paperclipai/paperclip","slug":"mcp-kind-not-found","errorCode":"mcp_${kind}_not_found","errorMessage":"Assigned MCP ${kind} was not found","messagePattern":"Assigned MCP (.+?) was not found","errorType":"http","errorClass":"ToolGatewayHttpError","httpStatus":404,"severity":"error","filePath":"server/src/services/tool-gateway.ts","lineNumber":5348,"sourceCode":"          prompts.push({\n            ...record,\n            name: contextHandle(\"prompt\", connection.id, record.name),\n            title: `${connection.name}: ${typeof record.title === \"string\" ? record.title : record.name}`,\n          });\n        }\n      }\n      return { prompts };\n    }\n    const kind = input.method === \"resources/read\" ? \"resource\" : \"prompt\";\n    const handle = parseContextHandle(\n      kind,\n      input.params?.[kind === \"resource\" ? \"uri\" : \"name\"],\n    );\n    const connection = handle\n      ? connections.find((candidate) => candidate.id === handle.connectionId)\n      : null;\n    if (!handle || !connection) {\n      throw new ToolGatewayHttpError(\n        404,\n        `Assigned MCP ${kind} was not found`,\n        `mcp_${kind}_not_found`,\n      );\n    }\n    const params =\n      kind === \"resource\"\n        ? { uri: handle.value }\n        : { name: handle.value, arguments: input.params?.arguments ?? {} };\n    const result = asRecord(\n      await callAssignedConnectionProtocol({\n        ...input,\n        session,\n        connection,\n        method: input.method,\n        params,\n      }),\n    );","sourceCodeStart":5330,"sourceCodeEnd":5366,"githubUrl":"https://github.com/paperclipai/paperclip/blob/3f1d897a7c018d76563a21c6e39c3c9b03933622/server/src/services/tool-gateway.ts#L5330-L5366","documentation":"The tool gateway resolves MCP resources/prompts through opaque context handles (e.g. 'ctx:<connectionId>:<uri>') produced by earlier tools/list, resources/list, or prompts/list calls. When handling resources/read, resources/get, or prompts/get, it parses the handle back into a connection ID and looks the connection up among the agent's assigned connections. If the handle is malformed, belongs to a different/unassigned connection, or the connection was removed, it throws this 404 ToolGatewayHttpError with reason code mcp_resource_not_found or mcp_prompt_not_found.","triggerScenarios":"Calling resources/read or prompts/get with a uri/name that is not a valid context handle, references a connectionId that is no longer in the caller's assigned connection list, or references a connection that was deleted or unassigned between the list call and the read call.","commonSituations":"A developer caches a resource URI from a previous session and reuses it after the MCP connection was disconnected or reassigned; a hand-written URI is passed instead of the handle returned by resources/list; the agent's connection assignments changed mid-session so the handle's connectionId no longer resolves.","solutions":["Re-run tools/list / resources/list / prompts/list against the current connection set and use a freshly returned handle instead of a cached or hand-built one.","Verify the MCP connection referenced by the handle is still assigned to this agent/company in the connections settings.","If passing raw URIs/names, wrap them via the gateway's context-handle format (connectionId + value) as produced by the list endpoints.","Check for stale clients holding handles across reconfiguration; refresh the session after changing connections."],"exampleFix":"// before\nawait gateway.invoke({ method: \"resources/read\", params: { uri: \"docs/readme\" } });\n// after\nconst { resources } = await gateway.invoke({ method: \"resources/list\", params: {} });\nawait gateway.invoke({ method: \"resources/read\", params: { uri: resources[0].uri } }); // use the returned context handle","handlingStrategy":"validation","validationCode":"function isValidResourceHandle(uri, assignedConnections) {\n  const m = /^ctx:[^:]+:(.+)$/.exec(String(uri ?? \"\"));\n  if (!m) return false;\n  return assignedConnections.some((c) => uri.startsWith(`ctx:${c.id}:`));\n}\nif (!isValidResourceHandle(params.uri, connections)) throw new Error(\"stale resource handle; re-list resources\");","typeGuard":"const isContextHandle = (v) => typeof v === \"string\" && /^ctx:[A-Za-z0-9-]+:/.test(v);","tryCatchPattern":"try {\n  await gateway.invoke({ method: \"resources/read\", params: { uri } });\n} catch (e) {\n  if (e.reasonCode === \"mcp_resource_not_found\" || e.reasonCode === \"mcp_prompt_not_found\") {\n    ({ resources } = await gateway.invoke({ method: \"resources/list\", params: {} })); // refresh handles and retry\n  } else throw e;\n}","preventionTips":["Always use handles returned by resources/list or prompts/list, never hand-built URIs.","Refresh cached handles after any change to the agent's connection assignments.","Re-list resources at the start of a session rather than reusing handles across sessions.","Monitor for connection removal events and invalidate cached handles."],"tags":["mcp","resource-not-found","stale-reference"],"backgroundTag":"record-not-found","analyzedSha":"3f1d897a7c018d76563a21c6e39c3c9b03933622","analyzedAt":"2026-09-18T08:03:59.046Z","contentChangedAt":"2026-09-18T08:03:59.046Z","schemaVersion":2},"datasetVersion":"2026-09-22T06:17:15.046Z"}