kojee-mcp 0.1.3 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/{chunk-AYJ6WN2K.js → chunk-RNKJONY3.js} +42 -212
- package/dist/cli.js +1 -1
- package/dist/index.js +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -6,7 +6,7 @@ kojee-mcp is a local MCP proxy that lets any MCP-capable agent use Kojee-managed
|
|
|
6
6
|
|
|
7
7
|
1. **Get a gateway token** from the [Kojee dashboard](https://kojee.ai).
|
|
8
8
|
2. **Add to your MCP config** (see examples below).
|
|
9
|
-
3. **Tools appear automatically** --
|
|
9
|
+
3. **Tools appear automatically** -- all Kojee tools your token has access to are exposed directly (e.g. `gmail_send_email`, `github_list_repos`, `calendar_create_event`). Agents call them like any native MCP tool — no discovery step, no wrapper, no indirection.
|
|
10
10
|
|
|
11
11
|
## MCP Config Examples
|
|
12
12
|
|
|
@@ -517,104 +517,56 @@ function sleep(ms) {
|
|
|
517
517
|
}
|
|
518
518
|
|
|
519
519
|
// src/tool-registry.ts
|
|
520
|
-
var BUILTIN_TOOL_NAMES = /* @__PURE__ */ new Set([
|
|
521
|
-
"kojee_check_approval",
|
|
522
|
-
"kojee_revoke_request",
|
|
523
|
-
"kojee_send_feedback"
|
|
524
|
-
]);
|
|
525
520
|
var ToolRegistry = class {
|
|
526
521
|
constructor(gateway) {
|
|
527
522
|
this.gateway = gateway;
|
|
528
523
|
}
|
|
529
524
|
gateway;
|
|
530
|
-
/**
|
|
531
|
-
|
|
532
|
-
/** All tool names (flat) for validation */
|
|
533
|
-
allToolNames = /* @__PURE__ */ new Set();
|
|
525
|
+
/** Flat map: tool name → full tool definition */
|
|
526
|
+
tools = /* @__PURE__ */ new Map();
|
|
534
527
|
/**
|
|
535
|
-
* Fetch
|
|
528
|
+
* Fetch all tools with full schemas from the gateway in a single RPC call.
|
|
536
529
|
*/
|
|
537
530
|
async discoverTools() {
|
|
538
|
-
console.error("[tools] Fetching
|
|
539
|
-
const
|
|
540
|
-
|
|
531
|
+
console.error("[tools] Fetching tools with full schemas from gateway...");
|
|
532
|
+
const result = await this.gateway.sendRpc("tools/list", {
|
|
533
|
+
include_schema: true
|
|
534
|
+
});
|
|
535
|
+
const maybeError = result;
|
|
536
|
+
if (maybeError.isError) {
|
|
537
|
+
const msg = maybeError.content?.[0]?.text ?? "unknown error";
|
|
538
|
+
throw new Error(`Gateway rejected tools/list: ${msg}`);
|
|
539
|
+
}
|
|
540
|
+
const toolList = result?.tools;
|
|
541
541
|
if (!toolList || !Array.isArray(toolList)) {
|
|
542
542
|
console.error("[tools] No tools returned from gateway");
|
|
543
543
|
return;
|
|
544
544
|
}
|
|
545
545
|
for (const tool of toolList) {
|
|
546
|
-
this.
|
|
547
|
-
|
|
548
|
-
const connector = tool._connector_id ?? (tool.name.includes("_") ? tool.name.substring(0, tool.name.indexOf("_")) : null);
|
|
549
|
-
if (!connector) {
|
|
550
|
-
console.error(`[tools] Skipping tool with no connector: ${tool.name}`);
|
|
551
|
-
continue;
|
|
546
|
+
if (this.tools.has(tool.name)) {
|
|
547
|
+
console.error(`[tools] Warning: duplicate tool name "${tool.name}" \u2014 overwriting`);
|
|
552
548
|
}
|
|
553
|
-
|
|
554
|
-
if (!info) {
|
|
555
|
-
info = { id: connector, tools: [] };
|
|
556
|
-
this.connectors.set(connector, info);
|
|
557
|
-
}
|
|
558
|
-
info.tools.push({ name: tool.name, description: tool.description });
|
|
559
|
-
}
|
|
560
|
-
console.error(
|
|
561
|
-
`[tools] Discovered ${this.allToolNames.size} tools across ${this.connectors.size} connectors`
|
|
562
|
-
);
|
|
563
|
-
}
|
|
564
|
-
/**
|
|
565
|
-
* Get the list of connector meta-tools to register with the MCP server.
|
|
566
|
-
* Each connector becomes a tool like "kojee_gmail" whose description
|
|
567
|
-
* lists its available tools.
|
|
568
|
-
*/
|
|
569
|
-
getConnectorTools() {
|
|
570
|
-
const tools = [];
|
|
571
|
-
for (const [connectorId, info] of this.connectors) {
|
|
572
|
-
const toolNames = info.tools.map((t) => t.name).join(", ");
|
|
573
|
-
tools.push({
|
|
574
|
-
name: connectorId,
|
|
575
|
-
description: `${connectorId} tools available via Kojee (${info.tools.length} tools: ${toolNames}). Call this tool to see descriptions and details for each.`,
|
|
576
|
-
inputSchema: { type: "object", properties: {} }
|
|
577
|
-
});
|
|
578
|
-
}
|
|
579
|
-
return tools;
|
|
580
|
-
}
|
|
581
|
-
/**
|
|
582
|
-
* Get the detailed tool list for a specific connector.
|
|
583
|
-
*/
|
|
584
|
-
getConnectorToolList(connectorId) {
|
|
585
|
-
const info = this.connectors.get(connectorId);
|
|
586
|
-
if (!info) {
|
|
587
|
-
return `No connector '${connectorId}' found. Available: ${Array.from(this.connectors.keys()).join(", ")}`;
|
|
549
|
+
this.tools.set(tool.name, tool);
|
|
588
550
|
}
|
|
589
|
-
|
|
590
|
-
return `## ${connectorId} tools
|
|
591
|
-
|
|
592
|
-
${lines.join("\n")}
|
|
593
|
-
|
|
594
|
-
Use kojee_get_tool_schema to get the full input schema, then kojee_call_tool to execute.`;
|
|
551
|
+
console.error(`[tools] Registered ${this.tools.size} tools from gateway`);
|
|
595
552
|
}
|
|
596
553
|
/**
|
|
597
|
-
*
|
|
554
|
+
* Return all registered tools for the MCP ListTools response.
|
|
598
555
|
*/
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
const response = result;
|
|
602
|
-
if (response.not_found && response.not_found.length > 0) {
|
|
603
|
-
console.error(`[tools] Schemas not found for: ${response.not_found.join(", ")}`);
|
|
604
|
-
}
|
|
605
|
-
return response.tools ?? [];
|
|
556
|
+
getAllTools() {
|
|
557
|
+
return Array.from(this.tools.values());
|
|
606
558
|
}
|
|
607
559
|
/**
|
|
608
560
|
* Call a tool through the gateway.
|
|
609
561
|
*/
|
|
610
562
|
async callTool(name, args) {
|
|
611
|
-
if (!this.
|
|
612
|
-
const available = Array.from(this.
|
|
563
|
+
if (!this.tools.has(name)) {
|
|
564
|
+
const available = Array.from(this.tools.keys()).slice(0, 10).join(", ");
|
|
613
565
|
return {
|
|
614
566
|
content: [
|
|
615
567
|
{
|
|
616
568
|
type: "text",
|
|
617
|
-
text: `Tool '${name}' not found.
|
|
569
|
+
text: `Tool '${name}' not found. Some available tools: ${available}${this.tools.size > 10 ? ", ..." : ""}`
|
|
618
570
|
}
|
|
619
571
|
],
|
|
620
572
|
isError: true
|
|
@@ -625,13 +577,9 @@ Use kojee_get_tool_schema to get the full input schema, then kojee_call_tool to
|
|
|
625
577
|
arguments: args
|
|
626
578
|
});
|
|
627
579
|
}
|
|
628
|
-
/**
|
|
629
|
-
get connectorIds() {
|
|
630
|
-
return Array.from(this.connectors.keys());
|
|
631
|
-
}
|
|
632
|
-
/** Total number of discovered tools. */
|
|
580
|
+
/** Total number of registered tools. */
|
|
633
581
|
get toolCount() {
|
|
634
|
-
return this.
|
|
582
|
+
return this.tools.size;
|
|
635
583
|
}
|
|
636
584
|
};
|
|
637
585
|
|
|
@@ -642,85 +590,11 @@ import {
|
|
|
642
590
|
ListToolsRequestSchema,
|
|
643
591
|
CallToolRequestSchema
|
|
644
592
|
} from "@modelcontextprotocol/sdk/types.js";
|
|
645
|
-
var UTILITY_TOOL_NAMES = /* @__PURE__ */ new Set([
|
|
646
|
-
"get_tool_schema",
|
|
647
|
-
"call_tool",
|
|
648
|
-
"check_approval",
|
|
649
|
-
"revoke_request"
|
|
650
|
-
]);
|
|
651
|
-
var UTILITY_TOOLS = [
|
|
652
|
-
{
|
|
653
|
-
name: "get_tool_schema",
|
|
654
|
-
description: "Get the full input schema for one or more Kojee tools. Call this before call_tool to know the exact parameters required.",
|
|
655
|
-
inputSchema: {
|
|
656
|
-
type: "object",
|
|
657
|
-
properties: {
|
|
658
|
-
names: {
|
|
659
|
-
type: "array",
|
|
660
|
-
items: { type: "string" },
|
|
661
|
-
description: 'Tool names to get schemas for (e.g. ["gmail_send_email", "github_list_repos"])'
|
|
662
|
-
}
|
|
663
|
-
},
|
|
664
|
-
required: ["names"]
|
|
665
|
-
}
|
|
666
|
-
},
|
|
667
|
-
{
|
|
668
|
-
name: "call_tool",
|
|
669
|
-
description: "Call a Kojee tool by name with the specified arguments. Use the connector tools (e.g. kojee_gmail) to discover tools, then get_tool_schema to get parameters, then this to execute.",
|
|
670
|
-
inputSchema: {
|
|
671
|
-
type: "object",
|
|
672
|
-
properties: {
|
|
673
|
-
name: {
|
|
674
|
-
type: "string",
|
|
675
|
-
description: 'The tool name (e.g. "gmail_send_email")'
|
|
676
|
-
},
|
|
677
|
-
arguments: {
|
|
678
|
-
type: "object",
|
|
679
|
-
description: "The tool arguments matching the tool's input schema",
|
|
680
|
-
additionalProperties: true
|
|
681
|
-
}
|
|
682
|
-
},
|
|
683
|
-
required: ["name"]
|
|
684
|
-
}
|
|
685
|
-
},
|
|
686
|
-
{
|
|
687
|
-
name: "check_approval",
|
|
688
|
-
description: "Check the status of a pending approval request. Use this after a tool call returns 'require_approval' to poll whether the user has approved or denied.",
|
|
689
|
-
inputSchema: {
|
|
690
|
-
type: "object",
|
|
691
|
-
properties: {
|
|
692
|
-
approval_id: {
|
|
693
|
-
type: "string",
|
|
694
|
-
description: "The approval ID returned when a tool call requires approval"
|
|
695
|
-
}
|
|
696
|
-
},
|
|
697
|
-
required: ["approval_id"]
|
|
698
|
-
}
|
|
699
|
-
},
|
|
700
|
-
{
|
|
701
|
-
name: "revoke_request",
|
|
702
|
-
description: "Revoke/cancel a pending approval request you no longer need.",
|
|
703
|
-
inputSchema: {
|
|
704
|
-
type: "object",
|
|
705
|
-
properties: {
|
|
706
|
-
approval_id: {
|
|
707
|
-
type: "string",
|
|
708
|
-
description: "The approval ID to revoke"
|
|
709
|
-
},
|
|
710
|
-
reason: {
|
|
711
|
-
type: "string",
|
|
712
|
-
description: "Optional reason for revoking"
|
|
713
|
-
}
|
|
714
|
-
},
|
|
715
|
-
required: ["approval_id"]
|
|
716
|
-
}
|
|
717
|
-
}
|
|
718
|
-
];
|
|
719
593
|
function createMcpServer(registry) {
|
|
720
594
|
const server = new Server(
|
|
721
595
|
{
|
|
722
596
|
name: "kojee-mcp",
|
|
723
|
-
version: "0.
|
|
597
|
+
version: "0.2.0"
|
|
724
598
|
},
|
|
725
599
|
{
|
|
726
600
|
capabilities: {
|
|
@@ -729,69 +603,21 @@ function createMcpServer(registry) {
|
|
|
729
603
|
}
|
|
730
604
|
);
|
|
731
605
|
server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
732
|
-
const
|
|
733
|
-
|
|
606
|
+
const tools = registry.getAllTools().map((t) => ({
|
|
607
|
+
name: t.name,
|
|
608
|
+
description: t.description,
|
|
609
|
+
inputSchema: t.inputSchema
|
|
610
|
+
}));
|
|
611
|
+
return { tools };
|
|
734
612
|
});
|
|
735
613
|
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
736
614
|
const { name, arguments: args } = request.params;
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
}
|
|
744
|
-
switch (name) {
|
|
745
|
-
case "get_tool_schema": {
|
|
746
|
-
const names = args?.names ?? [];
|
|
747
|
-
if (names.length === 0) {
|
|
748
|
-
return {
|
|
749
|
-
content: [{ type: "text", text: "Provide tool names in the 'names' array." }],
|
|
750
|
-
isError: true
|
|
751
|
-
};
|
|
752
|
-
}
|
|
753
|
-
const schemas = await registry.getToolSchemas(names);
|
|
754
|
-
return {
|
|
755
|
-
content: [{ type: "text", text: JSON.stringify(schemas, null, 2) }],
|
|
756
|
-
isError: false
|
|
757
|
-
};
|
|
758
|
-
}
|
|
759
|
-
case "call_tool": {
|
|
760
|
-
const toolName = args?.name;
|
|
761
|
-
if (!toolName) {
|
|
762
|
-
return {
|
|
763
|
-
content: [{ type: "text", text: "Provide the tool name in the 'name' field." }],
|
|
764
|
-
isError: true
|
|
765
|
-
};
|
|
766
|
-
}
|
|
767
|
-
const toolArgs = args?.arguments ?? {};
|
|
768
|
-
const rawResult = await registry.callTool(toolName, toolArgs);
|
|
769
|
-
const result = translateToolCallResult(rawResult);
|
|
770
|
-
return {
|
|
771
|
-
content: result.content,
|
|
772
|
-
isError: result.isError
|
|
773
|
-
};
|
|
774
|
-
}
|
|
775
|
-
case "check_approval":
|
|
776
|
-
case "revoke_request": {
|
|
777
|
-
const rawResult = await registry.callTool(name, args ?? {});
|
|
778
|
-
const result = translateToolCallResult(rawResult);
|
|
779
|
-
return {
|
|
780
|
-
content: result.content,
|
|
781
|
-
isError: result.isError
|
|
782
|
-
};
|
|
783
|
-
}
|
|
784
|
-
default:
|
|
785
|
-
return {
|
|
786
|
-
content: [
|
|
787
|
-
{
|
|
788
|
-
type: "text",
|
|
789
|
-
text: `Unknown tool '${name}'. Use one of the connector tools or utility tools.`
|
|
790
|
-
}
|
|
791
|
-
],
|
|
792
|
-
isError: true
|
|
793
|
-
};
|
|
794
|
-
}
|
|
615
|
+
const rawResult = await registry.callTool(name, args ?? {});
|
|
616
|
+
const result = translateToolCallResult(rawResult);
|
|
617
|
+
return {
|
|
618
|
+
content: result.content,
|
|
619
|
+
isError: result.isError
|
|
620
|
+
};
|
|
795
621
|
});
|
|
796
622
|
return server;
|
|
797
623
|
}
|
|
@@ -827,6 +653,10 @@ async function startProxy(config) {
|
|
|
827
653
|
`[kojee-mcp] Ready \u2014 ${registry.toolCount} tools available from ${config.url}`
|
|
828
654
|
);
|
|
829
655
|
const server = createMcpServer(registry);
|
|
656
|
+
process.stdin.on("end", () => {
|
|
657
|
+
console.error("[kojee-mcp] stdin closed, exiting");
|
|
658
|
+
process.exit(0);
|
|
659
|
+
});
|
|
830
660
|
await startMcpServer(server);
|
|
831
661
|
}
|
|
832
662
|
|
package/dist/cli.js
CHANGED
package/dist/index.js
CHANGED