@mseep/mcp-agent-social 1.1.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/LICENSE +21 -0
- package/README.md +154 -0
- package/bin/mcp-agent-social +30 -0
- package/dist/api-client.d.ts +31 -0
- package/dist/api-client.d.ts.map +1 -0
- package/dist/api-client.js +212 -0
- package/dist/api-client.js.map +1 -0
- package/dist/config.d.ts +19 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +79 -0
- package/dist/config.js.map +1 -0
- package/dist/hooks/index.d.ts +38 -0
- package/dist/hooks/index.d.ts.map +1 -0
- package/dist/hooks/index.js +253 -0
- package/dist/hooks/index.js.map +1 -0
- package/dist/hooks/types.d.ts +35 -0
- package/dist/hooks/types.d.ts.map +1 -0
- package/dist/hooks/types.js +4 -0
- package/dist/hooks/types.js.map +1 -0
- package/dist/http-server.d.ts +38 -0
- package/dist/http-server.d.ts.map +1 -0
- package/dist/http-server.js +210 -0
- package/dist/http-server.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +186 -0
- package/dist/index.js.map +1 -0
- package/dist/logger.d.ts +44 -0
- package/dist/logger.d.ts.map +1 -0
- package/dist/logger.js +281 -0
- package/dist/logger.js.map +1 -0
- package/dist/metrics.d.ts +47 -0
- package/dist/metrics.d.ts.map +1 -0
- package/dist/metrics.js +178 -0
- package/dist/metrics.js.map +1 -0
- package/dist/middleware/error-handler.d.ts +74 -0
- package/dist/middleware/error-handler.d.ts.map +1 -0
- package/dist/middleware/error-handler.js +218 -0
- package/dist/middleware/error-handler.js.map +1 -0
- package/dist/middleware/index.d.ts +55 -0
- package/dist/middleware/index.d.ts.map +1 -0
- package/dist/middleware/index.js +91 -0
- package/dist/middleware/index.js.map +1 -0
- package/dist/middleware/timeout.d.ts +52 -0
- package/dist/middleware/timeout.d.ts.map +1 -0
- package/dist/middleware/timeout.js +189 -0
- package/dist/middleware/timeout.js.map +1 -0
- package/dist/middleware/validator.d.ts +25 -0
- package/dist/middleware/validator.d.ts.map +1 -0
- package/dist/middleware/validator.js +186 -0
- package/dist/middleware/validator.js.map +1 -0
- package/dist/prompts/analyze.d.ts +46 -0
- package/dist/prompts/analyze.d.ts.map +1 -0
- package/dist/prompts/analyze.js +351 -0
- package/dist/prompts/analyze.js.map +1 -0
- package/dist/prompts/generate.d.ts +48 -0
- package/dist/prompts/generate.d.ts.map +1 -0
- package/dist/prompts/generate.js +177 -0
- package/dist/prompts/generate.js.map +1 -0
- package/dist/prompts/index.d.ts +23 -0
- package/dist/prompts/index.d.ts.map +1 -0
- package/dist/prompts/index.js +69 -0
- package/dist/prompts/index.js.map +1 -0
- package/dist/prompts/summarize.d.ts +32 -0
- package/dist/prompts/summarize.d.ts.map +1 -0
- package/dist/prompts/summarize.js +182 -0
- package/dist/prompts/summarize.js.map +1 -0
- package/dist/prompts/types.d.ts +34 -0
- package/dist/prompts/types.d.ts.map +1 -0
- package/dist/prompts/types.js +24 -0
- package/dist/prompts/types.js.map +1 -0
- package/dist/resources/agents.d.ts +17 -0
- package/dist/resources/agents.d.ts.map +1 -0
- package/dist/resources/agents.js +139 -0
- package/dist/resources/agents.js.map +1 -0
- package/dist/resources/feed.d.ts +19 -0
- package/dist/resources/feed.d.ts.map +1 -0
- package/dist/resources/feed.js +138 -0
- package/dist/resources/feed.js.map +1 -0
- package/dist/resources/index.d.ts +19 -0
- package/dist/resources/index.d.ts.map +1 -0
- package/dist/resources/index.js +146 -0
- package/dist/resources/index.js.map +1 -0
- package/dist/resources/posts.d.ts +17 -0
- package/dist/resources/posts.d.ts.map +1 -0
- package/dist/resources/posts.js +151 -0
- package/dist/resources/posts.js.map +1 -0
- package/dist/resources/types.d.ts +91 -0
- package/dist/resources/types.d.ts.map +1 -0
- package/dist/resources/types.js +12 -0
- package/dist/resources/types.js.map +1 -0
- package/dist/roots/index.d.ts +43 -0
- package/dist/roots/index.d.ts.map +1 -0
- package/dist/roots/index.js +131 -0
- package/dist/roots/index.js.map +1 -0
- package/dist/roots/types.d.ts +31 -0
- package/dist/roots/types.d.ts.map +1 -0
- package/dist/roots/types.js +4 -0
- package/dist/roots/types.js.map +1 -0
- package/dist/session-manager.d.ts +50 -0
- package/dist/session-manager.d.ts.map +1 -0
- package/dist/session-manager.js +127 -0
- package/dist/session-manager.js.map +1 -0
- package/dist/tools/create-post.d.ts +45 -0
- package/dist/tools/create-post.d.ts.map +1 -0
- package/dist/tools/create-post.js +119 -0
- package/dist/tools/create-post.js.map +1 -0
- package/dist/tools/index.d.ts +13 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +44 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/login.d.ts +35 -0
- package/dist/tools/login.d.ts.map +1 -0
- package/dist/tools/login.js +132 -0
- package/dist/tools/login.js.map +1 -0
- package/dist/tools/read-posts.d.ts +48 -0
- package/dist/tools/read-posts.d.ts.map +1 -0
- package/dist/tools/read-posts.js +93 -0
- package/dist/tools/read-posts.js.map +1 -0
- package/dist/types.d.ts +88 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +4 -0
- package/dist/types.js.map +1 -0
- package/dist/utils/json.d.ts +13 -0
- package/dist/utils/json.d.ts.map +1 -0
- package/dist/utils/json.js +48 -0
- package/dist/utils/json.js.map +1 -0
- package/dist/validation.d.ts +58 -0
- package/dist/validation.d.ts.map +1 -0
- package/dist/validation.js +223 -0
- package/dist/validation.js.map +1 -0
- package/package.json +70 -0
- package/src/api-client.ts +292 -0
- package/src/config.ts +92 -0
- package/src/hooks/index.ts +304 -0
- package/src/hooks/types.ts +44 -0
- package/src/http-server.ts +243 -0
- package/src/index.ts +213 -0
- package/src/logger.ts +326 -0
- package/src/metrics.ts +235 -0
- package/src/middleware/error-handler.ts +252 -0
- package/src/middleware/index.ts +112 -0
- package/src/middleware/timeout.ts +216 -0
- package/src/middleware/validator.ts +216 -0
- package/src/prompts/analyze.ts +404 -0
- package/src/prompts/generate.ts +217 -0
- package/src/prompts/index.ts +121 -0
- package/src/prompts/summarize.ts +217 -0
- package/src/prompts/types.ts +44 -0
- package/src/resources/agents.ts +165 -0
- package/src/resources/feed.ts +169 -0
- package/src/resources/index.ts +210 -0
- package/src/resources/posts.ts +179 -0
- package/src/resources/types.ts +104 -0
- package/src/roots/index.ts +166 -0
- package/src/roots/types.ts +36 -0
- package/src/session-manager.ts +149 -0
- package/src/tools/create-post.ts +154 -0
- package/src/tools/index.ts +70 -0
- package/src/tools/login.ts +169 -0
- package/src/tools/read-posts.ts +120 -0
- package/src/types.ts +107 -0
- package/src/utils/json.ts +46 -0
- package/src/validation.ts +322 -0
- package/tsconfig.json +22 -0
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
// ABOUTME: Main prompt registration and handling for MCP prompts
|
|
2
|
+
// ABOUTME: Coordinates all prompt types and implements list/get endpoints
|
|
3
|
+
|
|
4
|
+
import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
5
|
+
import type { RequestHandlerExtra } from '@modelcontextprotocol/sdk/shared/protocol.js';
|
|
6
|
+
import type {
|
|
7
|
+
GetPromptResult,
|
|
8
|
+
ListPromptsResult,
|
|
9
|
+
ServerNotification,
|
|
10
|
+
ServerRequest,
|
|
11
|
+
} from '@modelcontextprotocol/sdk/types.js';
|
|
12
|
+
import type { z } from 'zod';
|
|
13
|
+
import type { IApiClient } from '../api-client.js';
|
|
14
|
+
import { logger } from '../logger.js';
|
|
15
|
+
import type { SessionManager } from '../session-manager.js';
|
|
16
|
+
import { analyzePrompts } from './analyze.js';
|
|
17
|
+
import { generatePrompts } from './generate.js';
|
|
18
|
+
import { summarizePrompts } from './summarize.js';
|
|
19
|
+
|
|
20
|
+
export interface PromptContext {
|
|
21
|
+
apiClient: IApiClient;
|
|
22
|
+
sessionManager: SessionManager;
|
|
23
|
+
hooksManager?: any;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// Type for prompt handlers - use any for args since prompts have different arg types
|
|
27
|
+
type PromptHandler<T = any> = (
|
|
28
|
+
args: T,
|
|
29
|
+
extra: RequestHandlerExtra<ServerRequest, ServerNotification>,
|
|
30
|
+
context: PromptContext,
|
|
31
|
+
) => Promise<GetPromptResult>;
|
|
32
|
+
|
|
33
|
+
interface PromptDefinition {
|
|
34
|
+
description: string;
|
|
35
|
+
argsSchema: Record<string, z.ZodString | z.ZodOptional<z.ZodString>>;
|
|
36
|
+
handler: PromptHandler<any>;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// Combine all prompts
|
|
40
|
+
const allPrompts: Record<string, PromptDefinition> = {
|
|
41
|
+
// Summarization prompts
|
|
42
|
+
'summarize-thread': summarizePrompts.summarizeThread,
|
|
43
|
+
'summarize-agent-activity': summarizePrompts.summarizeAgentActivity,
|
|
44
|
+
|
|
45
|
+
// Generation prompts
|
|
46
|
+
'draft-reply': generatePrompts.draftReply,
|
|
47
|
+
'generate-hashtags': generatePrompts.generateHashtags,
|
|
48
|
+
'create-engagement-post': generatePrompts.createEngagementPost,
|
|
49
|
+
|
|
50
|
+
// Analysis prompts
|
|
51
|
+
'analyze-sentiment': analyzePrompts.analyzeSentiment,
|
|
52
|
+
'find-related-discussions': analyzePrompts.findRelatedDiscussions,
|
|
53
|
+
'generate-engagement-report': analyzePrompts.generateEngagementReport,
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Register all prompts with the MCP server
|
|
58
|
+
*/
|
|
59
|
+
export function registerPrompts(server: McpServer, context: PromptContext): void {
|
|
60
|
+
logger.info('Registering MCP prompts');
|
|
61
|
+
|
|
62
|
+
// Register each prompt
|
|
63
|
+
for (const [name, prompt] of Object.entries(allPrompts)) {
|
|
64
|
+
server.prompt(
|
|
65
|
+
name,
|
|
66
|
+
prompt.description,
|
|
67
|
+
prompt.argsSchema,
|
|
68
|
+
async (args: any, extra: RequestHandlerExtra<ServerRequest, ServerNotification>) => {
|
|
69
|
+
logger.debug(`Executing prompt: ${name}`, { args });
|
|
70
|
+
return prompt.handler(args, extra, context);
|
|
71
|
+
},
|
|
72
|
+
);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
logger.info('Prompts registered', {
|
|
76
|
+
count: Object.keys(allPrompts).length,
|
|
77
|
+
prompts: Object.keys(allPrompts),
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* List all available prompts
|
|
83
|
+
*/
|
|
84
|
+
export async function listPrompts(): Promise<ListPromptsResult> {
|
|
85
|
+
logger.debug('Listing all prompts');
|
|
86
|
+
|
|
87
|
+
const prompts = Object.entries(allPrompts).map(([name, prompt]) => ({
|
|
88
|
+
name,
|
|
89
|
+
description: prompt.description,
|
|
90
|
+
arguments: Object.entries(prompt.argsSchema).map(([argName, schema]) => ({
|
|
91
|
+
name: argName,
|
|
92
|
+
description: schema._def.description || '',
|
|
93
|
+
required: !schema.isOptional(),
|
|
94
|
+
})),
|
|
95
|
+
}));
|
|
96
|
+
|
|
97
|
+
return { prompts };
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Get a specific prompt by name
|
|
102
|
+
*/
|
|
103
|
+
export async function getPrompt(
|
|
104
|
+
name: string,
|
|
105
|
+
args: Record<string, string>,
|
|
106
|
+
context: PromptContext,
|
|
107
|
+
extra?: RequestHandlerExtra<ServerRequest, ServerNotification>,
|
|
108
|
+
): Promise<GetPromptResult | null> {
|
|
109
|
+
const prompt = allPrompts[name];
|
|
110
|
+
if (!prompt) {
|
|
111
|
+
logger.warn('Prompt not found', { name });
|
|
112
|
+
return null;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// If no extra provided, this shouldn't be called directly
|
|
116
|
+
if (!extra) {
|
|
117
|
+
throw new Error('getPrompt requires RequestHandlerExtra parameter');
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
return prompt.handler(args, extra, context);
|
|
121
|
+
}
|
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
// ABOUTME: Summarization prompts for threads and conversations
|
|
2
|
+
// ABOUTME: Provides templates for summarizing social media content
|
|
3
|
+
|
|
4
|
+
import type { RequestHandlerExtra } from '@modelcontextprotocol/sdk/shared/protocol.js';
|
|
5
|
+
import type {
|
|
6
|
+
GetPromptResult,
|
|
7
|
+
ServerNotification,
|
|
8
|
+
ServerRequest,
|
|
9
|
+
} from '@modelcontextprotocol/sdk/types.js';
|
|
10
|
+
import { z } from 'zod';
|
|
11
|
+
import type { IApiClient } from '../api-client.js';
|
|
12
|
+
import { config } from '../config.js';
|
|
13
|
+
import { logger } from '../logger.js';
|
|
14
|
+
|
|
15
|
+
export interface SummarizePromptContext {
|
|
16
|
+
apiClient: IApiClient;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const summarizeThreadArgsSchema = {
|
|
20
|
+
thread_id: z.string().describe('The ID of the thread to summarize'),
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
export async function summarizeThreadPrompt(
|
|
24
|
+
args: { thread_id: string },
|
|
25
|
+
_extra: RequestHandlerExtra<ServerRequest, ServerNotification>,
|
|
26
|
+
context: SummarizePromptContext,
|
|
27
|
+
): Promise<GetPromptResult> {
|
|
28
|
+
try {
|
|
29
|
+
logger.debug('Generating thread summary prompt', { threadId: args.thread_id });
|
|
30
|
+
|
|
31
|
+
// Fetch the thread posts
|
|
32
|
+
const response = await context.apiClient.fetchPosts(config.teamName, {
|
|
33
|
+
thread_id: args.thread_id,
|
|
34
|
+
limit: 100,
|
|
35
|
+
offset: 0,
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
if (!response.posts || response.posts.length === 0) {
|
|
39
|
+
return {
|
|
40
|
+
description: 'Thread not found',
|
|
41
|
+
messages: [
|
|
42
|
+
{
|
|
43
|
+
role: 'user',
|
|
44
|
+
content: {
|
|
45
|
+
type: 'text',
|
|
46
|
+
text: `Unable to find thread with ID: ${args.thread_id}`,
|
|
47
|
+
},
|
|
48
|
+
},
|
|
49
|
+
],
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// Build the conversation history
|
|
54
|
+
const conversation = response.posts
|
|
55
|
+
.sort((a, b) => a.timestamp.localeCompare(b.timestamp))
|
|
56
|
+
.map((post) => `${post.author_name}: ${post.content}`)
|
|
57
|
+
.join('\n\n');
|
|
58
|
+
|
|
59
|
+
// Count unique participants
|
|
60
|
+
const participants = new Set(response.posts.map((p) => p.author_name));
|
|
61
|
+
|
|
62
|
+
return {
|
|
63
|
+
description: 'Summarize a social media conversation thread',
|
|
64
|
+
messages: [
|
|
65
|
+
{
|
|
66
|
+
role: 'user',
|
|
67
|
+
content: {
|
|
68
|
+
type: 'text',
|
|
69
|
+
text: `Please summarize the following social media conversation thread:
|
|
70
|
+
|
|
71
|
+
Thread ID: ${args.thread_id}
|
|
72
|
+
Participants: ${participants.size} (${Array.from(participants).join(', ')})
|
|
73
|
+
Total Posts: ${response.posts.length}
|
|
74
|
+
|
|
75
|
+
Conversation:
|
|
76
|
+
${conversation}
|
|
77
|
+
|
|
78
|
+
Please provide:
|
|
79
|
+
1. A brief summary of the main topic(s) discussed
|
|
80
|
+
2. Key points or decisions made
|
|
81
|
+
3. Any action items or follow-ups mentioned
|
|
82
|
+
4. The overall sentiment/tone of the conversation`,
|
|
83
|
+
},
|
|
84
|
+
},
|
|
85
|
+
],
|
|
86
|
+
};
|
|
87
|
+
} catch (error) {
|
|
88
|
+
logger.error('Error generating thread summary prompt', { error, threadId: args.thread_id });
|
|
89
|
+
return {
|
|
90
|
+
description: 'Error generating prompt',
|
|
91
|
+
messages: [
|
|
92
|
+
{
|
|
93
|
+
role: 'user',
|
|
94
|
+
content: {
|
|
95
|
+
type: 'text',
|
|
96
|
+
text: `Error fetching thread data: ${error instanceof Error ? error.message : 'Unknown error'}`,
|
|
97
|
+
},
|
|
98
|
+
},
|
|
99
|
+
],
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
const summarizeAgentArgsSchema = {
|
|
105
|
+
agent_name: z.string().describe('The name of the agent to summarize'),
|
|
106
|
+
limit: z.string().optional().describe('Maximum number of posts to analyze (default: 20)'),
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
export async function summarizeAgentActivityPrompt(
|
|
110
|
+
args: { agent_name: string; limit?: string },
|
|
111
|
+
_extra: RequestHandlerExtra<ServerRequest, ServerNotification>,
|
|
112
|
+
context: SummarizePromptContext,
|
|
113
|
+
): Promise<GetPromptResult> {
|
|
114
|
+
try {
|
|
115
|
+
const limit = args.limit ? Number.parseInt(args.limit, 10) : 20;
|
|
116
|
+
logger.debug('Generating agent activity summary prompt', { agentName: args.agent_name, limit });
|
|
117
|
+
|
|
118
|
+
// Fetch the agent's posts
|
|
119
|
+
const response = await context.apiClient.fetchPosts(config.teamName, {
|
|
120
|
+
agent_filter: args.agent_name,
|
|
121
|
+
limit,
|
|
122
|
+
offset: 0,
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
if (!response.posts || response.posts.length === 0) {
|
|
126
|
+
return {
|
|
127
|
+
description: 'Agent not found or has no posts',
|
|
128
|
+
messages: [
|
|
129
|
+
{
|
|
130
|
+
role: 'user',
|
|
131
|
+
content: {
|
|
132
|
+
type: 'text',
|
|
133
|
+
text: `No posts found for agent: ${args.agent_name}`,
|
|
134
|
+
},
|
|
135
|
+
},
|
|
136
|
+
],
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
// Analyze post patterns
|
|
141
|
+
const posts = response.posts.sort((a, b) => b.timestamp.localeCompare(a.timestamp));
|
|
142
|
+
const tags = posts.flatMap((p) => p.tags || []);
|
|
143
|
+
const tagCounts = tags.reduce(
|
|
144
|
+
(acc, tag) => {
|
|
145
|
+
acc[tag] = (acc[tag] || 0) + 1;
|
|
146
|
+
return acc;
|
|
147
|
+
},
|
|
148
|
+
{} as Record<string, number>,
|
|
149
|
+
);
|
|
150
|
+
|
|
151
|
+
const recentPosts = posts
|
|
152
|
+
.slice(0, 5)
|
|
153
|
+
.map((p) => `- ${p.content}${p.tags?.length ? ` [${p.tags.join(', ')}]` : ''}`)
|
|
154
|
+
.join('\n');
|
|
155
|
+
|
|
156
|
+
return {
|
|
157
|
+
description: `Summarize ${args.agent_name}'s social media activity`,
|
|
158
|
+
messages: [
|
|
159
|
+
{
|
|
160
|
+
role: 'user',
|
|
161
|
+
content: {
|
|
162
|
+
type: 'text',
|
|
163
|
+
text: `Please analyze and summarize the social media activity for agent "${args.agent_name}":
|
|
164
|
+
|
|
165
|
+
Total Posts: ${response.total || response.posts.length}
|
|
166
|
+
Posts Analyzed: ${posts.length}
|
|
167
|
+
Time Range: ${posts[posts.length - 1]?.timestamp} to ${posts[0]?.timestamp}
|
|
168
|
+
|
|
169
|
+
Most Used Tags: ${Object.entries(tagCounts)
|
|
170
|
+
.sort(([, a], [, b]) => b - a)
|
|
171
|
+
.slice(0, 5)
|
|
172
|
+
.map(([tag, count]) => `${tag} (${count})`)
|
|
173
|
+
.join(', ')}
|
|
174
|
+
|
|
175
|
+
Recent Posts:
|
|
176
|
+
${recentPosts}
|
|
177
|
+
|
|
178
|
+
Please provide:
|
|
179
|
+
1. A summary of this agent's main topics of interest
|
|
180
|
+
2. Their posting patterns and frequency
|
|
181
|
+
3. Their communication style and tone
|
|
182
|
+
4. Key themes or recurring subjects in their posts
|
|
183
|
+
5. Their level of engagement with others (replies vs original posts)`,
|
|
184
|
+
},
|
|
185
|
+
},
|
|
186
|
+
],
|
|
187
|
+
};
|
|
188
|
+
} catch (error) {
|
|
189
|
+
logger.error('Error generating agent summary prompt', { error, agentName: args.agent_name });
|
|
190
|
+
return {
|
|
191
|
+
description: 'Error generating prompt',
|
|
192
|
+
messages: [
|
|
193
|
+
{
|
|
194
|
+
role: 'user',
|
|
195
|
+
content: {
|
|
196
|
+
type: 'text',
|
|
197
|
+
text: `Error fetching agent data: ${error instanceof Error ? error.message : 'Unknown error'}`,
|
|
198
|
+
},
|
|
199
|
+
},
|
|
200
|
+
],
|
|
201
|
+
};
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
// Export schemas for registration
|
|
206
|
+
export const summarizePrompts = {
|
|
207
|
+
summarizeThread: {
|
|
208
|
+
description: 'Generate a summary of a conversation thread',
|
|
209
|
+
argsSchema: summarizeThreadArgsSchema,
|
|
210
|
+
handler: summarizeThreadPrompt,
|
|
211
|
+
},
|
|
212
|
+
summarizeAgentActivity: {
|
|
213
|
+
description: "Summarize an agent's posting patterns and activity",
|
|
214
|
+
argsSchema: summarizeAgentArgsSchema,
|
|
215
|
+
handler: summarizeAgentActivityPrompt,
|
|
216
|
+
},
|
|
217
|
+
};
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
// ABOUTME: Type definitions for MCP prompts in the social media server
|
|
2
|
+
// ABOUTME: Defines prompt structures and interfaces
|
|
3
|
+
|
|
4
|
+
import { z } from 'zod';
|
|
5
|
+
|
|
6
|
+
export interface PromptMessage {
|
|
7
|
+
role: 'user' | 'assistant';
|
|
8
|
+
content: {
|
|
9
|
+
type: 'text';
|
|
10
|
+
text: string;
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export interface PromptTemplate {
|
|
15
|
+
name: string;
|
|
16
|
+
description?: string;
|
|
17
|
+
arguments?: Record<string, z.ZodString | z.ZodOptional<z.ZodString>>;
|
|
18
|
+
messages: PromptMessage[];
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// Prompt argument schemas
|
|
22
|
+
export const threadIdSchema = {
|
|
23
|
+
thread_id: z.string().describe('The ID of the thread to analyze'),
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
export const agentNameSchema = {
|
|
27
|
+
agent_name: z.string().describe('The name of the agent to analyze'),
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
export const postContentSchema = {
|
|
31
|
+
post_content: z.string().describe('The content of the post to analyze or reply to'),
|
|
32
|
+
context: z.string().optional().describe('Additional context about the conversation'),
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
export const topicSchema = {
|
|
36
|
+
topic: z.string().describe('The topic or theme to search for'),
|
|
37
|
+
limit: z.string().optional().describe('Maximum number of results to return'),
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
export const timeRangeSchema = {
|
|
41
|
+
start_date: z.string().optional().describe('Start date for the report (ISO format)'),
|
|
42
|
+
end_date: z.string().optional().describe('End date for the report (ISO format)'),
|
|
43
|
+
agent_filter: z.string().optional().describe('Filter by specific agent name'),
|
|
44
|
+
};
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
// ABOUTME: Agent resource handlers for reading agent profiles and posts
|
|
2
|
+
// ABOUTME: Implements resource callbacks for agent-related URIs
|
|
3
|
+
|
|
4
|
+
import type { URL } from 'node:url';
|
|
5
|
+
import type { ReadResourceResult } from '@modelcontextprotocol/sdk/types.js';
|
|
6
|
+
import type { IApiClient } from '../api-client.js';
|
|
7
|
+
import { config } from '../config.js';
|
|
8
|
+
import { logger } from '../logger.js';
|
|
9
|
+
import type { AgentPostsResource, AgentProfileResource } from './types.js';
|
|
10
|
+
|
|
11
|
+
export interface AgentResourceContext {
|
|
12
|
+
apiClient: IApiClient;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Read an agent's profile
|
|
17
|
+
* URI: social://agents/{agentName}/profile
|
|
18
|
+
*/
|
|
19
|
+
export async function readAgentProfileResource(
|
|
20
|
+
uri: URL,
|
|
21
|
+
context: AgentResourceContext,
|
|
22
|
+
): Promise<ReadResourceResult> {
|
|
23
|
+
try {
|
|
24
|
+
// Extract agentName from URI path
|
|
25
|
+
const pathMatch = uri.pathname.match(/^\/\/agents\/([^/]+)\/profile$/);
|
|
26
|
+
const agentName = pathMatch?.[1];
|
|
27
|
+
|
|
28
|
+
if (!agentName) {
|
|
29
|
+
return {
|
|
30
|
+
contents: [
|
|
31
|
+
{
|
|
32
|
+
uri: uri.toString(),
|
|
33
|
+
mimeType: 'application/json',
|
|
34
|
+
text: JSON.stringify({ error: 'Invalid agent profile URI: missing agentName' }),
|
|
35
|
+
},
|
|
36
|
+
],
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
logger.debug('Reading agent profile resource', { agentName });
|
|
41
|
+
|
|
42
|
+
// Fetch all posts by this agent to build profile
|
|
43
|
+
const response = await context.apiClient.fetchPosts(config.teamName, {
|
|
44
|
+
agent_filter: agentName,
|
|
45
|
+
limit: 100,
|
|
46
|
+
offset: 0,
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
// Calculate profile stats
|
|
50
|
+
let firstSeenAt: string | undefined;
|
|
51
|
+
let lastSeenAt: string | undefined;
|
|
52
|
+
|
|
53
|
+
if (response.posts.length > 0) {
|
|
54
|
+
const timestamps = response.posts.map((p) => p.timestamp);
|
|
55
|
+
timestamps.sort();
|
|
56
|
+
firstSeenAt = timestamps[0];
|
|
57
|
+
lastSeenAt = timestamps[timestamps.length - 1];
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
const resource: AgentProfileResource = {
|
|
61
|
+
profile: {
|
|
62
|
+
agentName,
|
|
63
|
+
postCount: response.total || response.posts.length,
|
|
64
|
+
firstSeenAt,
|
|
65
|
+
lastSeenAt,
|
|
66
|
+
},
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
return {
|
|
70
|
+
contents: [
|
|
71
|
+
{
|
|
72
|
+
uri: uri.toString(),
|
|
73
|
+
mimeType: 'application/json',
|
|
74
|
+
text: JSON.stringify(resource, null, 2),
|
|
75
|
+
},
|
|
76
|
+
],
|
|
77
|
+
};
|
|
78
|
+
} catch (error) {
|
|
79
|
+
logger.error('Error reading agent profile resource', { error, uri: uri.toString() });
|
|
80
|
+
return {
|
|
81
|
+
contents: [
|
|
82
|
+
{
|
|
83
|
+
uri: uri.toString(),
|
|
84
|
+
mimeType: 'application/json',
|
|
85
|
+
text: JSON.stringify({
|
|
86
|
+
error: 'Failed to read agent profile resource',
|
|
87
|
+
details: error instanceof Error ? error.message : 'Unknown error',
|
|
88
|
+
}),
|
|
89
|
+
},
|
|
90
|
+
],
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Read an agent's posts
|
|
97
|
+
* URI: social://agents/{agentName}/posts
|
|
98
|
+
*/
|
|
99
|
+
export async function readAgentPostsResource(
|
|
100
|
+
uri: URL,
|
|
101
|
+
context: AgentResourceContext,
|
|
102
|
+
): Promise<ReadResourceResult> {
|
|
103
|
+
try {
|
|
104
|
+
// Extract agentName from URI path
|
|
105
|
+
const pathMatch = uri.pathname.match(/^\/\/agents\/([^/]+)\/posts$/);
|
|
106
|
+
const agentName = pathMatch?.[1];
|
|
107
|
+
|
|
108
|
+
if (!agentName) {
|
|
109
|
+
return {
|
|
110
|
+
contents: [
|
|
111
|
+
{
|
|
112
|
+
uri: uri.toString(),
|
|
113
|
+
mimeType: 'application/json',
|
|
114
|
+
text: JSON.stringify({ error: 'Invalid agent posts URI: missing agentName' }),
|
|
115
|
+
},
|
|
116
|
+
],
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
logger.debug('Reading agent posts resource', { agentName });
|
|
121
|
+
|
|
122
|
+
// Fetch posts by this agent
|
|
123
|
+
const response = await context.apiClient.fetchPosts(config.teamName, {
|
|
124
|
+
agent_filter: agentName,
|
|
125
|
+
limit: 50, // Reasonable default
|
|
126
|
+
offset: 0,
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
const resource: AgentPostsResource = {
|
|
130
|
+
agentName,
|
|
131
|
+
posts: response.posts.map((p) => ({
|
|
132
|
+
id: p.id,
|
|
133
|
+
content: p.content,
|
|
134
|
+
tags: p.tags,
|
|
135
|
+
timestamp: p.timestamp,
|
|
136
|
+
parent_post_id: p.parent_post_id,
|
|
137
|
+
})),
|
|
138
|
+
total: response.total || response.posts.length,
|
|
139
|
+
};
|
|
140
|
+
|
|
141
|
+
return {
|
|
142
|
+
contents: [
|
|
143
|
+
{
|
|
144
|
+
uri: uri.toString(),
|
|
145
|
+
mimeType: 'application/json',
|
|
146
|
+
text: JSON.stringify(resource, null, 2),
|
|
147
|
+
},
|
|
148
|
+
],
|
|
149
|
+
};
|
|
150
|
+
} catch (error) {
|
|
151
|
+
logger.error('Error reading agent posts resource', { error, uri: uri.toString() });
|
|
152
|
+
return {
|
|
153
|
+
contents: [
|
|
154
|
+
{
|
|
155
|
+
uri: uri.toString(),
|
|
156
|
+
mimeType: 'application/json',
|
|
157
|
+
text: JSON.stringify({
|
|
158
|
+
error: 'Failed to read agent posts resource',
|
|
159
|
+
details: error instanceof Error ? error.message : 'Unknown error',
|
|
160
|
+
}),
|
|
161
|
+
},
|
|
162
|
+
],
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
}
|