kojee-mcp 0.1.3 → 0.2.0
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-O5UYOIQX.js} +33 -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,51 @@ 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 toolList = result?.tools;
|
|
541
536
|
if (!toolList || !Array.isArray(toolList)) {
|
|
542
537
|
console.error("[tools] No tools returned from gateway");
|
|
543
538
|
return;
|
|
544
539
|
}
|
|
545
540
|
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;
|
|
552
|
-
}
|
|
553
|
-
let info = this.connectors.get(connector);
|
|
554
|
-
if (!info) {
|
|
555
|
-
info = { id: connector, tools: [] };
|
|
556
|
-
this.connectors.set(connector, info);
|
|
541
|
+
if (this.tools.has(tool.name)) {
|
|
542
|
+
console.error(`[tools] Warning: duplicate tool name "${tool.name}" \u2014 overwriting`);
|
|
557
543
|
}
|
|
558
|
-
|
|
544
|
+
this.tools.set(tool.name, tool);
|
|
559
545
|
}
|
|
560
|
-
console.error(
|
|
561
|
-
`[tools] Discovered ${this.allToolNames.size} tools across ${this.connectors.size} connectors`
|
|
562
|
-
);
|
|
546
|
+
console.error(`[tools] Registered ${this.tools.size} tools from gateway`);
|
|
563
547
|
}
|
|
564
548
|
/**
|
|
565
|
-
*
|
|
566
|
-
* Each connector becomes a tool like "kojee_gmail" whose description
|
|
567
|
-
* lists its available tools.
|
|
549
|
+
* Return all registered tools for the MCP ListTools response.
|
|
568
550
|
*/
|
|
569
|
-
|
|
570
|
-
|
|
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(", ")}`;
|
|
588
|
-
}
|
|
589
|
-
const lines = info.tools.map((t) => `- **${t.name}**: ${t.description}`);
|
|
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.`;
|
|
595
|
-
}
|
|
596
|
-
/**
|
|
597
|
-
* Get full schemas for specific tools via tools/get_schema.
|
|
598
|
-
*/
|
|
599
|
-
async getToolSchemas(names) {
|
|
600
|
-
const result = await this.gateway.sendRpc("tools/get_schema", { names });
|
|
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 ?? [];
|
|
551
|
+
getAllTools() {
|
|
552
|
+
return Array.from(this.tools.values());
|
|
606
553
|
}
|
|
607
554
|
/**
|
|
608
555
|
* Call a tool through the gateway.
|
|
609
556
|
*/
|
|
610
557
|
async callTool(name, args) {
|
|
611
|
-
if (!this.
|
|
612
|
-
const available = Array.from(this.
|
|
558
|
+
if (!this.tools.has(name)) {
|
|
559
|
+
const available = Array.from(this.tools.keys()).slice(0, 10).join(", ");
|
|
613
560
|
return {
|
|
614
561
|
content: [
|
|
615
562
|
{
|
|
616
563
|
type: "text",
|
|
617
|
-
text: `Tool '${name}' not found.
|
|
564
|
+
text: `Tool '${name}' not found. Some available tools: ${available}${this.tools.size > 10 ? ", ..." : ""}`
|
|
618
565
|
}
|
|
619
566
|
],
|
|
620
567
|
isError: true
|
|
@@ -625,13 +572,9 @@ Use kojee_get_tool_schema to get the full input schema, then kojee_call_tool to
|
|
|
625
572
|
arguments: args
|
|
626
573
|
});
|
|
627
574
|
}
|
|
628
|
-
/**
|
|
629
|
-
get connectorIds() {
|
|
630
|
-
return Array.from(this.connectors.keys());
|
|
631
|
-
}
|
|
632
|
-
/** Total number of discovered tools. */
|
|
575
|
+
/** Total number of registered tools. */
|
|
633
576
|
get toolCount() {
|
|
634
|
-
return this.
|
|
577
|
+
return this.tools.size;
|
|
635
578
|
}
|
|
636
579
|
};
|
|
637
580
|
|
|
@@ -642,85 +585,11 @@ import {
|
|
|
642
585
|
ListToolsRequestSchema,
|
|
643
586
|
CallToolRequestSchema
|
|
644
587
|
} 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
588
|
function createMcpServer(registry) {
|
|
720
589
|
const server = new Server(
|
|
721
590
|
{
|
|
722
591
|
name: "kojee-mcp",
|
|
723
|
-
version: "0.
|
|
592
|
+
version: "0.2.0"
|
|
724
593
|
},
|
|
725
594
|
{
|
|
726
595
|
capabilities: {
|
|
@@ -729,69 +598,21 @@ function createMcpServer(registry) {
|
|
|
729
598
|
}
|
|
730
599
|
);
|
|
731
600
|
server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
732
|
-
const
|
|
733
|
-
|
|
601
|
+
const tools = registry.getAllTools().map((t) => ({
|
|
602
|
+
name: t.name,
|
|
603
|
+
description: t.description,
|
|
604
|
+
inputSchema: t.inputSchema
|
|
605
|
+
}));
|
|
606
|
+
return { tools };
|
|
734
607
|
});
|
|
735
608
|
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
736
609
|
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
|
-
}
|
|
610
|
+
const rawResult = await registry.callTool(name, args ?? {});
|
|
611
|
+
const result = translateToolCallResult(rawResult);
|
|
612
|
+
return {
|
|
613
|
+
content: result.content,
|
|
614
|
+
isError: result.isError
|
|
615
|
+
};
|
|
795
616
|
});
|
|
796
617
|
return server;
|
|
797
618
|
}
|
package/dist/cli.js
CHANGED
package/dist/index.js
CHANGED