mirror of
https://github.com/simplex-chat/simplex-chat.git
synced 2026-10-24 14:59:57 +00:00
* packages: simplex-chat MCP server * update * standing approvals per chat, leave tool, simplify * fixes * add error messages * LICENSE * specification * migration * update simplex-chat, tests, fixes * update simplex-chat libraries * use agent peer type * better server and tool descriptions * short readme * reference * images * update readme * update readme * update * change links to master * fix links to point to master branch --------- Co-authored-by: Evgeny @ SimpleX Chat <259188159+evgeny-simplex@users.noreply.github.com>
58 lines
2.3 KiB
TypeScript
58 lines
2.3 KiB
TypeScript
const modernVersion = "2026-07-28"
|
|
|
|
export interface ToolOutcome {
|
|
isError?: boolean
|
|
text: string
|
|
result: any
|
|
}
|
|
|
|
export class McpClient {
|
|
private nextId = 1
|
|
|
|
constructor(private readonly url: string, private readonly token: string) {}
|
|
|
|
async initialize(): Promise<any> {
|
|
const id = this.nextId++
|
|
const response = await fetch(this.url, {
|
|
method: "POST",
|
|
headers: {authorization: `Bearer ${this.token}`, "content-type": "application/json", accept: "application/json, text/event-stream"},
|
|
body: JSON.stringify({jsonrpc: "2.0", id, method: "initialize", params: {protocolVersion: "2025-11-25", capabilities: {}, clientInfo: {name: "e2e", version: "1"}}}),
|
|
})
|
|
return reply(response, id, "initialize")
|
|
}
|
|
|
|
async request(method: string, params: object = {}, signal?: AbortSignal): Promise<any> {
|
|
const id = this.nextId++
|
|
const name = (params as {name?: string}).name
|
|
const response = await fetch(this.url, {
|
|
method: "POST",
|
|
signal,
|
|
headers: {
|
|
authorization: `Bearer ${this.token}`,
|
|
"content-type": "application/json",
|
|
accept: "application/json, text/event-stream",
|
|
"mcp-protocol-version": modernVersion,
|
|
"mcp-method": method,
|
|
...(name === undefined ? {} : {"mcp-name": name}),
|
|
},
|
|
body: JSON.stringify({jsonrpc: "2.0", id, method, params: {...params, _meta: {"io.modelcontextprotocol/protocolVersion": modernVersion, "io.modelcontextprotocol/clientCapabilities": {}}}}),
|
|
})
|
|
return reply(response, id, method)
|
|
}
|
|
|
|
async tool(name: string, args: object, signal?: AbortSignal): Promise<ToolOutcome> {
|
|
const result = await this.request("tools/call", {name, arguments: args}, signal)
|
|
return {isError: result.isError, text: result.content[0].text, result: result.structuredContent}
|
|
}
|
|
}
|
|
|
|
async function reply(response: Response, id: number, method: string): Promise<any> {
|
|
const text = await response.text()
|
|
const messages = response.headers.get("content-type")?.startsWith("text/event-stream")
|
|
? text.split("\n").filter(line => line.startsWith("data: ")).map(line => JSON.parse(line.slice(6)))
|
|
: [JSON.parse(text)]
|
|
const message = messages.find(({id: messageId}) => messageId === id)
|
|
if (message.error) throw new Error(`${method}: ${JSON.stringify(message.error)}`)
|
|
return message.result
|
|
}
|