@ezmodo/mcp-server 0.13.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 +305 -0
- package/config/development.js +20 -0
- package/config/endpoint-map.js +351 -0
- package/config/index.js +34 -0
- package/config/production.js +18 -0
- package/config/staging.js +18 -0
- package/handlers/access.js +141 -0
- package/handlers/activity.js +112 -0
- package/handlers/agents.js +95 -0
- package/handlers/ai-intelligence.js +55 -0
- package/handlers/attachments.js +30 -0
- package/handlers/catalogs.js +169 -0
- package/handlers/components.js +282 -0
- package/handlers/context-manifest.js +1150 -0
- package/handlers/decisions.js +114 -0
- package/handlers/designs.js +118 -0
- package/handlers/documents.js +227 -0
- package/handlers/entities.js +95 -0
- package/handlers/epics.js +190 -0
- package/handlers/facts.js +62 -0
- package/handlers/feature-flags.js +142 -0
- package/handlers/features.js +137 -0
- package/handlers/folders.js +127 -0
- package/handlers/git-context.js +917 -0
- package/handlers/github.js +72 -0
- package/handlers/graph.js +23 -0
- package/handlers/index.js +205 -0
- package/handlers/links.js +156 -0
- package/handlers/milestones.js +131 -0
- package/handlers/organizations.js +14 -0
- package/handlers/projects.js +122 -0
- package/handlers/recurring-tasks.js +33 -0
- package/handlers/tags.js +124 -0
- package/handlers/tasks.js +561 -0
- package/handlers/testing.js +116 -0
- package/handlers/todos.js +43 -0
- package/handlers/watchers.js +54 -0
- package/handlers/work-templates.js +32 -0
- package/index.js +175 -0
- package/lib/active-session.js +86 -0
- package/lib/auto-assign.js +93 -0
- package/lib/autolink.js +176 -0
- package/lib/changed-files.js +22 -0
- package/lib/env.js +45 -0
- package/lib/git-helpers.js +553 -0
- package/lib/git-utils.js +73 -0
- package/lib/http-client.js +164 -0
- package/lib/links-at-create.js +94 -0
- package/lib/local-cache.js +140 -0
- package/lib/logger.js +109 -0
- package/lib/manifest-loader.js +182 -0
- package/lib/manifest-query.js +686 -0
- package/lib/repo-config-dir.js +118 -0
- package/lib/version.js +10 -0
- package/lib/web-url.js +69 -0
- package/lib/worktree-tools.js +950 -0
- package/package.json +62 -0
- package/prompts/ai-workflow-automation.js +96 -0
- package/prompts/index.js +39 -0
- package/prompts/zephly-usage-guide-content.txt +631 -0
- package/prompts/zephly-usage-guide.js +119 -0
- package/tools/access-entity-types.js +28 -0
- package/tools/access.js +152 -0
- package/tools/activity.js +38 -0
- package/tools/agents.js +208 -0
- package/tools/ai-intelligence.js +111 -0
- package/tools/attachments.js +92 -0
- package/tools/catalogs.js +341 -0
- package/tools/components.js +249 -0
- package/tools/context-manifest.js +236 -0
- package/tools/decisions.js +168 -0
- package/tools/designs.js +222 -0
- package/tools/documents.js +287 -0
- package/tools/entities.js +223 -0
- package/tools/epics.js +267 -0
- package/tools/facts.js +70 -0
- package/tools/feature-flags.js +300 -0
- package/tools/features.js +246 -0
- package/tools/folders.js +122 -0
- package/tools/git-context.js +109 -0
- package/tools/github.js +172 -0
- package/tools/graph.js +70 -0
- package/tools/index.js +77 -0
- package/tools/link-params.js +93 -0
- package/tools/linkable-types.js +36 -0
- package/tools/links.js +199 -0
- package/tools/milestones.js +176 -0
- package/tools/organizations.js +23 -0
- package/tools/projects.js +172 -0
- package/tools/recurring-tasks.js +115 -0
- package/tools/tags.js +219 -0
- package/tools/task-item-schema.js +57 -0
- package/tools/task-type.js +33 -0
- package/tools/tasks.js +680 -0
- package/tools/testing.js +344 -0
- package/tools/todos.js +69 -0
- package/tools/watchers.js +81 -0
- package/tools/work-templates.js +96 -0
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Project Handlers
|
|
3
|
+
* Handler functions for project-related MCP tools
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { callZephlyAPI } from '../lib/http-client.js';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Dispatch manage_project actions
|
|
10
|
+
*/
|
|
11
|
+
export async function manageProject(args) {
|
|
12
|
+
const { action, ...params } = args;
|
|
13
|
+
switch (action) {
|
|
14
|
+
case 'create': return createProject(params);
|
|
15
|
+
case 'update': return updateProject(params);
|
|
16
|
+
case 'generate_how_it_works': return generateProjectHowItWorks(params);
|
|
17
|
+
case 'apply_how_it_works': return applyProjectHowItWorks(params);
|
|
18
|
+
default: throw new Error(`Unknown action: ${action}`);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Unified get_project handler — by ID (context), search, or list all
|
|
24
|
+
*/
|
|
25
|
+
export async function getProject(args) {
|
|
26
|
+
const { projectId, query } = args;
|
|
27
|
+
|
|
28
|
+
// Mode 1: get project context by ID
|
|
29
|
+
if (projectId) {
|
|
30
|
+
return callZephlyAPI('mcpGetProjectContext', { projectId });
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// Mode 2: search by query text, or list all
|
|
34
|
+
if (query || args.type || args.organizationId) {
|
|
35
|
+
return searchProjects(args);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// Mode 3: list all
|
|
39
|
+
return callZephlyAPI('mcpListProjects', {});
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
async function createProject(args) {
|
|
43
|
+
return callZephlyAPI('mcpCreateProject', args);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// Update an existing project. Only the fields present in `args` are changed —
|
|
47
|
+
// the server leaves anything unmentioned alone. This is the path that lets an
|
|
48
|
+
// agent set gitUrl/gitProvider after creation, which is what commit-to-task
|
|
49
|
+
// linking and component link resolution key off.
|
|
50
|
+
async function updateProject(args) {
|
|
51
|
+
return callZephlyAPI('mcpUpdateProject', args);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// Generate (and persist) the project's grounded "how it works" living description
|
|
55
|
+
// via the model. AI-quota gated server-side (mirrors entities.generateGoalHowItWorks).
|
|
56
|
+
async function generateProjectHowItWorks({ projectId }) {
|
|
57
|
+
return callZephlyAPI('mcpGenerateProjectHowItWorks', { projectId });
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// Apply (persist) a LOCAL-agent-authored "how it works" for a project (BYO-AI,
|
|
61
|
+
// E-190). Cited sources are validated server-side before saving; no model call.
|
|
62
|
+
async function applyProjectHowItWorks({ projectId, markdown, sources }) {
|
|
63
|
+
return callZephlyAPI('mcpApplyProjectHowItWorks', { projectId, markdown, sources });
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// Project Story (E-208): a grounded, source-attributed narrative of what has
|
|
67
|
+
// happened to a project since it began. Returns a fresh cached story when
|
|
68
|
+
// available, otherwise generates one (AI-quota gated server-side).
|
|
69
|
+
export async function getProjectStory({ projectId, window, from, to }) {
|
|
70
|
+
return callZephlyAPI('mcpGetProjectStory', { projectId, window, from, to });
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
async function searchProjects(args) {
|
|
74
|
+
const {
|
|
75
|
+
query: searchText,
|
|
76
|
+
type,
|
|
77
|
+
organizationId,
|
|
78
|
+
limit = 50,
|
|
79
|
+
} = args;
|
|
80
|
+
|
|
81
|
+
try {
|
|
82
|
+
const allProjects = await callZephlyAPI('mcpListProjects', {});
|
|
83
|
+
|
|
84
|
+
// callZephlyAPI already unwrapped the {success, data} envelope, so what
|
|
85
|
+
// arrives is `{projects: [...]}` with no `success` flag. Testing for one
|
|
86
|
+
// sent every search down this branch and returned the whole unfiltered
|
|
87
|
+
// list -- a `query` that matched nothing was indistinguishable from one
|
|
88
|
+
// that matched everything.
|
|
89
|
+
if (!Array.isArray(allProjects?.projects)) {
|
|
90
|
+
return allProjects;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
let filtered = allProjects.projects;
|
|
94
|
+
|
|
95
|
+
if (searchText) {
|
|
96
|
+
const searchLower = searchText.toLowerCase();
|
|
97
|
+
filtered = filtered.filter((project) =>
|
|
98
|
+
project.name.toLowerCase().includes(searchLower) ||
|
|
99
|
+
(project.description && project.description.toLowerCase().includes(searchLower))
|
|
100
|
+
);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
if (type) {
|
|
104
|
+
filtered = filtered.filter((project) => project.type === type);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
if (organizationId) {
|
|
108
|
+
filtered = filtered.filter((project) => project.organizationId === organizationId);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
filtered = filtered.slice(0, limit);
|
|
112
|
+
|
|
113
|
+
return {
|
|
114
|
+
success: true,
|
|
115
|
+
projects: filtered,
|
|
116
|
+
count: filtered.length,
|
|
117
|
+
totalBeforeLimit: allProjects.projects.length,
|
|
118
|
+
};
|
|
119
|
+
} catch (error) {
|
|
120
|
+
throw new Error(`Failed to search projects: ${error.message}`);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Recurring Task Schedule Handlers
|
|
3
|
+
* Handler for the E-211 recurrence-engine MCP tool.
|
|
4
|
+
*
|
|
5
|
+
* Thin wrappers over /api/mcp/v1/recurring-tasks; validation, next_run_at
|
|
6
|
+
* computation, and the schedule lifecycle happen server-side in
|
|
7
|
+
* core/recurringtasks.Service.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import { callZephlyAPI } from '../lib/http-client.js';
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Dispatch manage_recurring_task actions.
|
|
14
|
+
*/
|
|
15
|
+
export async function manageRecurringTask(args) {
|
|
16
|
+
const { action, ...params } = args;
|
|
17
|
+
switch (action) {
|
|
18
|
+
case 'create': return callZephlyAPI('mcpCreateRecurringTask', params);
|
|
19
|
+
case 'update': return callZephlyAPI('mcpUpdateRecurringTask', params);
|
|
20
|
+
case 'pause': return callZephlyAPI('mcpPauseRecurringTask', { scheduleId: params.scheduleId });
|
|
21
|
+
case 'resume': return callZephlyAPI('mcpResumeRecurringTask', { scheduleId: params.scheduleId });
|
|
22
|
+
case 'delete': return callZephlyAPI('mcpDeleteRecurringTask', { scheduleId: params.scheduleId });
|
|
23
|
+
case 'get': return callZephlyAPI('mcpGetRecurringTask', { scheduleId: params.scheduleId });
|
|
24
|
+
case 'list': {
|
|
25
|
+
const listParams = {};
|
|
26
|
+
if (params.organizationId) listParams.organizationId = params.organizationId;
|
|
27
|
+
if (params.projectId) listParams.projectId = params.projectId;
|
|
28
|
+
return callZephlyAPI('mcpListRecurringTasks', listParams);
|
|
29
|
+
}
|
|
30
|
+
default:
|
|
31
|
+
throw new Error(`Unknown action: ${action}. Expected create, update, pause, resume, delete, list, or get.`);
|
|
32
|
+
}
|
|
33
|
+
}
|
package/handlers/tags.js
ADDED
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tag Handlers
|
|
3
|
+
* Handler functions for tag operations
|
|
4
|
+
*
|
|
5
|
+
* Consolidated: manageTag dispatches create/update/delete/merge/bulk_tag.
|
|
6
|
+
* listTags unifies get/list/findEntities/suggest.
|
|
7
|
+
*
|
|
8
|
+
* list_tags uses local cache for unfiltered requests, falling back to API.
|
|
9
|
+
* Write operations (create, update, delete, merge) invalidate the cache.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import { callZephlyAPI } from '../lib/http-client.js';
|
|
13
|
+
import { getCachedTags, updateCacheSections, invalidateCacheSection } from '../lib/local-cache.js';
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Dispatch manage_tag actions to the appropriate handler
|
|
17
|
+
*/
|
|
18
|
+
export async function manageTag(args) {
|
|
19
|
+
const { action, ...params } = args;
|
|
20
|
+
switch (action) {
|
|
21
|
+
case 'create': return createTag(params);
|
|
22
|
+
case 'update': return updateTag(params);
|
|
23
|
+
case 'delete': return deleteTag(params);
|
|
24
|
+
case 'merge': return mergeTags(params);
|
|
25
|
+
case 'bulk_tag': return bulkTagEntities(params);
|
|
26
|
+
default: throw new Error(`Unknown action: ${action}`);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Unified list/get/find/suggest handler for tags
|
|
32
|
+
*/
|
|
33
|
+
export async function listTags(args) {
|
|
34
|
+
// Strip routing flags before passing to helpers
|
|
35
|
+
const { suggest, findEntities, ...params } = args;
|
|
36
|
+
|
|
37
|
+
// Mode 1: suggest tags
|
|
38
|
+
if (suggest) {
|
|
39
|
+
return suggestTags(params);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// Mode 2: find entities by tags
|
|
43
|
+
if (findEntities) {
|
|
44
|
+
return findEntitiesByTags(params);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// Mode 3: single tag lookup by ID or name
|
|
48
|
+
if (params.tagId || params.name) {
|
|
49
|
+
return getTag(params);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// Mode 4: list tags with optional filters
|
|
53
|
+
return listTagsFiltered(params);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// --- Private helpers ---
|
|
57
|
+
|
|
58
|
+
async function createTag(args) {
|
|
59
|
+
const result = await callZephlyAPI('mcpCreateTag', args);
|
|
60
|
+
await invalidateCacheSection('tags');
|
|
61
|
+
return result;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
async function updateTag(args) {
|
|
65
|
+
const result = await callZephlyAPI('mcpUpdateTag', args);
|
|
66
|
+
await invalidateCacheSection('tags');
|
|
67
|
+
return result;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
async function deleteTag(args) {
|
|
71
|
+
const result = await callZephlyAPI('mcpDeleteTag', args);
|
|
72
|
+
await invalidateCacheSection('tags');
|
|
73
|
+
return result;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
async function mergeTags(args) {
|
|
77
|
+
const result = await callZephlyAPI('mcpMergeTags', args);
|
|
78
|
+
await invalidateCacheSection('tags');
|
|
79
|
+
return result;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
async function bulkTagEntities(args) {
|
|
83
|
+
return callZephlyAPI('mcpBulkTagEntities', args);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
async function getTag(args) {
|
|
87
|
+
return callZephlyAPI('mcpGetTag', args);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
async function listTagsFiltered(args) {
|
|
91
|
+
const hasFilters = args.category || args.searchQuery || args.pinnedOnly || args.includeHidden || args.projectId;
|
|
92
|
+
|
|
93
|
+
if (!hasFilters) {
|
|
94
|
+
const cached = await getCachedTags();
|
|
95
|
+
if (cached !== null) {
|
|
96
|
+
return { tags: cached, cached: true };
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// Call API
|
|
101
|
+
const result = await callZephlyAPI('mcpListTags', args);
|
|
102
|
+
|
|
103
|
+
// Cache unfiltered results for future use
|
|
104
|
+
if (!hasFilters && result?.tags) {
|
|
105
|
+
const summaries = result.tags.map((t) => ({
|
|
106
|
+
id: t.id,
|
|
107
|
+
name: t.name,
|
|
108
|
+
color: t.color || '',
|
|
109
|
+
category: t.category || 'custom',
|
|
110
|
+
description: t.description || '',
|
|
111
|
+
}));
|
|
112
|
+
await updateCacheSections({ tags: summaries });
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
return result;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
async function findEntitiesByTags(args) {
|
|
119
|
+
return callZephlyAPI('mcpFindEntitiesByTags', args);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
async function suggestTags(args) {
|
|
123
|
+
return callZephlyAPI('mcpSuggestTags', args);
|
|
124
|
+
}
|