talking-stick 0.1.4 → 0.3.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.
@@ -1,212 +0,0 @@
1
- import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
- import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
3
- import { z } from "zod";
4
- import { isProtocolError } from "./errors.js";
5
- import { deriveMcpHarnessIdentity } from "./identity.js";
6
- import { createSystemProcessInspector } from "./process-utils.js";
7
- import { TalkingStickCommands } from "./commands.js";
8
- import { TalkingStickService } from "./service.js";
9
- const handoffSchema = z
10
- .object({
11
- status: z.string(),
12
- next_action: z.string(),
13
- artifacts: z
14
- .array(z.object({
15
- path: z.string(),
16
- lines: z.array(z.number().int()).length(2).optional(),
17
- role: z.enum(["examine", "review", "edit", "context", "output"]),
18
- note: z.string().optional()
19
- }))
20
- .optional(),
21
- open_questions: z.array(z.string()).optional(),
22
- do_not: z.array(z.string()).optional()
23
- })
24
- .passthrough();
25
- export function createMcpServer(service = new TalkingStickService()) {
26
- const commands = new TalkingStickCommands(service);
27
- const resolveConnectionIdentity = createConnectionIdentityResolver();
28
- const server = new McpServer({
29
- name: "talking-stick",
30
- version: "0.1.2"
31
- });
32
- server.registerTool("list_rooms", {
33
- title: "List Rooms",
34
- description: "List talking-stick rooms, optionally scoped to a path.",
35
- inputSchema: {
36
- context_path: z.string().optional()
37
- }
38
- }, async (input) => toolJson(() => service.listRooms(input)));
39
- server.registerTool("join_path", {
40
- title: "Join Path",
41
- description: "Join the room resolved from an invocation context path.",
42
- inputSchema: {
43
- context_path: z.string().min(1),
44
- force_new: z.boolean().optional(),
45
- agent_id_override: z.string().min(1).optional()
46
- }
47
- }, async (input, extra) => toolJson(() => commands.joinPath(resolveConnectionIdentity(extra.sessionId, input.agent_id_override), {
48
- context_path: input.context_path,
49
- force_new: input.force_new
50
- })));
51
- server.registerTool("leave_room", {
52
- title: "Leave Room",
53
- description: "Explicitly leave a room. The room is deleted when no active members remain.",
54
- inputSchema: {
55
- room_id: z.string().min(1)
56
- }
57
- }, async (input, extra) => toolJson(() => commands.leaveRoom(resolveConnectionIdentity(extra.sessionId), input)));
58
- server.registerTool("kick_member", {
59
- title: "Kick Member",
60
- description: "Remove an idle member from a room. Without force, only succeeds if the target's process is detected gone past the silence-grace window.",
61
- inputSchema: {
62
- room_id: z.string().min(1),
63
- target_agent_id: z.string().min(1),
64
- force: z.boolean().optional(),
65
- reason: z.string().optional()
66
- }
67
- }, async (input, extra) => toolJson(() => commands.kickMember(resolveConnectionIdentity(extra.sessionId), input)));
68
- server.registerTool("wait_for_turn", {
69
- title: "Wait For Turn",
70
- description: "Poll until the caller can claim the stick or takeover is available.",
71
- inputSchema: {
72
- room_id: z.string().min(1),
73
- max_wait_ms: z.number().int().nonnegative().optional()
74
- }
75
- }, async (input, extra) => toolJson(() => commands.waitForTurn(resolveConnectionIdentity(extra.sessionId), input)));
76
- server.registerTool("heartbeat", {
77
- title: "Heartbeat",
78
- description: "Renew the current owner's lease.",
79
- inputSchema: ownerMutationSchema()
80
- }, async (input, extra) => toolJson(() => commands.heartbeat(resolveConnectionIdentity(extra.sessionId), input)));
81
- server.registerTool("release_stick", {
82
- title: "Release Stick",
83
- description: "Release the stick to the next active member in sequence.",
84
- inputSchema: {
85
- ...ownerMutationSchema(),
86
- handoff: handoffSchema
87
- }
88
- }, async (input, extra) => toolJson(() => commands.releaseStick(resolveConnectionIdentity(extra.sessionId), input)));
89
- server.registerTool("pass_stick", {
90
- title: "Pass Stick",
91
- description: "Pass the stick to a specific active member.",
92
- inputSchema: {
93
- ...ownerMutationSchema(),
94
- to_agent_id: z.string().min(1),
95
- handoff: handoffSchema
96
- }
97
- }, async (input, extra) => toolJson(() => commands.passStick(resolveConnectionIdentity(extra.sessionId), input)));
98
- server.registerTool("takeover_stick", {
99
- title: "Takeover Stick",
100
- description: "Explicitly take over after claim timeout or owner lease timeout.",
101
- inputSchema: {
102
- room_id: z.string().min(1),
103
- expected_turn_id: z.number().int().nonnegative(),
104
- reason: z.string().min(1)
105
- }
106
- }, async (input, extra) => toolJson(() => commands.takeoverStick(resolveConnectionIdentity(extra.sessionId), input)));
107
- server.registerTool("get_room_state", {
108
- title: "Get Room State",
109
- description: "Read the current projected room state and membership.",
110
- inputSchema: {
111
- room_id: z.string().min(1)
112
- }
113
- }, async (input, extra) => toolJson(() => commands.getRoomState({
114
- ...input,
115
- agent_id: resolveConnectionIdentity(extra.sessionId).agent_id
116
- })));
117
- server.registerTool("get_room_events", {
118
- title: "Get Room Events",
119
- description: "Read the append-only event log for a room.",
120
- inputSchema: {
121
- room_id: z.string().min(1),
122
- after_event_seq: z.number().int().nonnegative().optional(),
123
- limit: z.number().int().positive().optional()
124
- }
125
- }, async (input, extra) => toolJson(() => commands.getRoomEvents({
126
- ...input,
127
- agent_id: resolveConnectionIdentity(extra.sessionId).agent_id
128
- })));
129
- server.registerTool("add_note", {
130
- title: "Add Note",
131
- description: "Leave an async note on a room. Any joined member can author; authoring refreshes presence.",
132
- inputSchema: {
133
- room_id: z.string().min(1),
134
- body: z.string().min(1),
135
- turn_id: z.number().int().nonnegative().optional()
136
- }
137
- }, async (input, extra) => toolJson(() => commands.addNote(resolveConnectionIdentity(extra.sessionId), input)));
138
- server.registerTool("list_notes", {
139
- title: "List Notes",
140
- description: "List notes for a room. Default view hides resolved notes; pagination uses after_note_id.",
141
- inputSchema: {
142
- room_id: z.string().min(1),
143
- after_note_id: z.string().min(1).optional(),
144
- include_resolved: z.boolean().optional(),
145
- limit: z.number().int().positive().max(200).optional()
146
- }
147
- }, async (input, extra) => toolJson(() => commands.listNotes(resolveConnectionIdentity(extra.sessionId), input)));
148
- return server;
149
- }
150
- export function createConnectionIdentityResolver(options = {}) {
151
- const inspector = options.inspector ?? createSystemProcessInspector({ cacheTtlMs: 60_000 });
152
- const connectionOverrides = new Map();
153
- const connectionIdentities = new Map();
154
- return (sessionId, override) => {
155
- const key = sessionId ?? "__stdio__";
156
- if (override) {
157
- connectionOverrides.set(key, override);
158
- connectionIdentities.delete(key);
159
- }
160
- const cached = connectionIdentities.get(key);
161
- if (cached) {
162
- return cached;
163
- }
164
- const identity = deriveMcpHarnessIdentity({
165
- sessionId,
166
- agentId: connectionOverrides.get(key),
167
- inspector
168
- });
169
- connectionIdentities.set(key, identity);
170
- return identity;
171
- };
172
- }
173
- export async function runStdioServer() {
174
- const service = new TalkingStickService();
175
- const server = createMcpServer(service);
176
- process.on("exit", () => service.close());
177
- await server.connect(new StdioServerTransport());
178
- }
179
- function ownerMutationSchema() {
180
- return {
181
- room_id: z.string().min(1),
182
- lease_id: z.string().min(1),
183
- expected_turn_id: z.number().int().nonnegative()
184
- };
185
- }
186
- async function toolJson(fn) {
187
- try {
188
- const result = await fn();
189
- return {
190
- content: [
191
- {
192
- type: "text",
193
- text: JSON.stringify(result, null, 2)
194
- }
195
- ]
196
- };
197
- }
198
- catch (error) {
199
- if (isProtocolError(error)) {
200
- return {
201
- isError: true,
202
- content: [
203
- {
204
- type: "text",
205
- text: JSON.stringify(error.toJSON(), null, 2)
206
- }
207
- ]
208
- };
209
- }
210
- throw error;
211
- }
212
- }
package/dist/server.js DELETED
@@ -1,3 +0,0 @@
1
- #!/usr/bin/env node
2
- import { runStdioServer } from "./mcp-server.js";
3
- await runStdioServer();