workday-studio-mcp-server 2.0.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/.env.example +40 -0
- package/LICENSE +21 -0
- package/README.md +258 -0
- package/dist/config.d.ts +22 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +67 -0
- package/dist/config.js.map +1 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +84 -0
- package/dist/index.js.map +1 -0
- package/dist/schemas/index.d.ts +473 -0
- package/dist/schemas/index.d.ts.map +1 -0
- package/dist/schemas/index.js +172 -0
- package/dist/schemas/index.js.map +1 -0
- package/dist/tools/copy-file.d.ts +7 -0
- package/dist/tools/copy-file.d.ts.map +1 -0
- package/dist/tools/copy-file.js +82 -0
- package/dist/tools/copy-file.js.map +1 -0
- package/dist/tools/delete-file.d.ts +7 -0
- package/dist/tools/delete-file.d.ts.map +1 -0
- package/dist/tools/delete-file.js +85 -0
- package/dist/tools/delete-file.js.map +1 -0
- package/dist/tools/list-assembly-steps.d.ts +7 -0
- package/dist/tools/list-assembly-steps.d.ts.map +1 -0
- package/dist/tools/list-assembly-steps.js +107 -0
- package/dist/tools/list-assembly-steps.js.map +1 -0
- package/dist/tools/list-files.d.ts +7 -0
- package/dist/tools/list-files.d.ts.map +1 -0
- package/dist/tools/list-files.js +66 -0
- package/dist/tools/list-files.js.map +1 -0
- package/dist/tools/list-integration-params.d.ts +7 -0
- package/dist/tools/list-integration-params.d.ts.map +1 -0
- package/dist/tools/list-integration-params.js +95 -0
- package/dist/tools/list-integration-params.js.map +1 -0
- package/dist/tools/list-projects.d.ts +7 -0
- package/dist/tools/list-projects.d.ts.map +1 -0
- package/dist/tools/list-projects.js +68 -0
- package/dist/tools/list-projects.js.map +1 -0
- package/dist/tools/read-file.d.ts +7 -0
- package/dist/tools/read-file.d.ts.map +1 -0
- package/dist/tools/read-file.js +63 -0
- package/dist/tools/read-file.js.map +1 -0
- package/dist/tools/rename-file.d.ts +7 -0
- package/dist/tools/rename-file.d.ts.map +1 -0
- package/dist/tools/rename-file.js +86 -0
- package/dist/tools/rename-file.js.map +1 -0
- package/dist/tools/search-files.d.ts +7 -0
- package/dist/tools/search-files.d.ts.map +1 -0
- package/dist/tools/search-files.js +110 -0
- package/dist/tools/search-files.js.map +1 -0
- package/dist/tools/validate-xml.d.ts +7 -0
- package/dist/tools/validate-xml.d.ts.map +1 -0
- package/dist/tools/validate-xml.js +69 -0
- package/dist/tools/validate-xml.js.map +1 -0
- package/dist/tools/workspace-tree.d.ts +7 -0
- package/dist/tools/workspace-tree.d.ts.map +1 -0
- package/dist/tools/workspace-tree.js +93 -0
- package/dist/tools/workspace-tree.js.map +1 -0
- package/dist/tools/write-file.d.ts +7 -0
- package/dist/tools/write-file.d.ts.map +1 -0
- package/dist/tools/write-file.js +87 -0
- package/dist/tools/write-file.js.map +1 -0
- package/dist/utils/errors.d.ts +42 -0
- package/dist/utils/errors.d.ts.map +1 -0
- package/dist/utils/errors.js +50 -0
- package/dist/utils/errors.js.map +1 -0
- package/dist/utils/fs.d.ts +17 -0
- package/dist/utils/fs.d.ts.map +1 -0
- package/dist/utils/fs.js +35 -0
- package/dist/utils/fs.js.map +1 -0
- package/dist/utils/logger.d.ts +24 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +56 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/utils/xml.d.ts +14 -0
- package/dist/utils/xml.d.ts.map +1 -0
- package/dist/utils/xml.js +31 -0
- package/dist/utils/xml.js.map +1 -0
- package/package.json +66 -0
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* read_project_file — read the contents of a project file.
|
|
3
|
+
*/
|
|
4
|
+
import { readFileSync, statSync } from 'fs';
|
|
5
|
+
import { join } from 'path';
|
|
6
|
+
import { getConfig } from '../config.js';
|
|
7
|
+
import { errorResponse } from '../utils/errors.js';
|
|
8
|
+
import { logger } from '../utils/logger.js';
|
|
9
|
+
import { resolveSafe } from '../utils/fs.js';
|
|
10
|
+
import { ReadFileSchema } from '../schemas/index.js';
|
|
11
|
+
export const TOOL_NAME = 'read_project_file';
|
|
12
|
+
const DESCRIPTION = 'Read the contents of any file in a Workday Studio project. ' +
|
|
13
|
+
'Returns the raw text content (XML, XSL, JSON, etc.).';
|
|
14
|
+
export function register(server) {
|
|
15
|
+
server.tool(TOOL_NAME, DESCRIPTION, ReadFileSchema.shape, async ({ project_name, file_path }) => {
|
|
16
|
+
const cfg = getConfig();
|
|
17
|
+
logger.info('Reading project file', {
|
|
18
|
+
context: 'ToolExecution',
|
|
19
|
+
tool: TOOL_NAME,
|
|
20
|
+
project: project_name,
|
|
21
|
+
file: file_path,
|
|
22
|
+
});
|
|
23
|
+
const projectDir = join(cfg.workspacePath, project_name);
|
|
24
|
+
try {
|
|
25
|
+
statSync(projectDir);
|
|
26
|
+
}
|
|
27
|
+
catch {
|
|
28
|
+
return errorResponse('PROJECT_NOT_FOUND', `Project '${project_name}' does not exist.`, 'Use list_studio_projects to see available projects.');
|
|
29
|
+
}
|
|
30
|
+
let resolved;
|
|
31
|
+
try {
|
|
32
|
+
resolved = resolveSafe(project_name, file_path);
|
|
33
|
+
}
|
|
34
|
+
catch (err) {
|
|
35
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
36
|
+
return errorResponse('PATH_TRAVERSAL_DETECTED', msg);
|
|
37
|
+
}
|
|
38
|
+
try {
|
|
39
|
+
statSync(resolved.absolute);
|
|
40
|
+
}
|
|
41
|
+
catch {
|
|
42
|
+
return errorResponse('FILE_NOT_FOUND', `File '${file_path}' not found in project '${project_name}'.`, 'Use list_project_files to see available files.');
|
|
43
|
+
}
|
|
44
|
+
try {
|
|
45
|
+
const content = readFileSync(resolved.absolute, 'utf-8');
|
|
46
|
+
return {
|
|
47
|
+
content: [{ type: 'text', text: content }],
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
catch (err) {
|
|
51
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
52
|
+
logger.error('Failed to read file', {
|
|
53
|
+
context: 'ToolExecution',
|
|
54
|
+
tool: TOOL_NAME,
|
|
55
|
+
project: project_name,
|
|
56
|
+
file: file_path,
|
|
57
|
+
error: msg,
|
|
58
|
+
});
|
|
59
|
+
return errorResponse('READ_ERROR', `Failed to read file: ${msg}`);
|
|
60
|
+
}
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
//# sourceMappingURL=read-file.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"read-file.js","sourceRoot":"","sources":["../../src/tools/read-file.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,IAAI,CAAC;AAC5C,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAE5B,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AACzC,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAC5C,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAC7C,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAErD,MAAM,CAAC,MAAM,SAAS,GAAG,mBAAmB,CAAC;AAE7C,MAAM,WAAW,GACf,6DAA6D;IAC7D,sDAAsD,CAAC;AAEzD,MAAM,UAAU,QAAQ,CAAC,MAAiB;IACxC,MAAM,CAAC,IAAI,CACT,SAAS,EACT,WAAW,EACX,cAAc,CAAC,KAAK,EACpB,KAAK,EAAE,EAAE,YAAY,EAAE,SAAS,EAAE,EAAE,EAAE;QACpC,MAAM,GAAG,GAAG,SAAS,EAAE,CAAC;QACxB,MAAM,CAAC,IAAI,CAAC,sBAAsB,EAAE;YAClC,OAAO,EAAE,eAAe;YACxB,IAAI,EAAE,SAAS;YACf,OAAO,EAAE,YAAY;YACrB,IAAI,EAAE,SAAS;SAChB,CAAC,CAAC;QAEH,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,CAAC,aAAa,EAAE,YAAY,CAAC,CAAC;QACzD,IAAI,CAAC;YACH,QAAQ,CAAC,UAAU,CAAC,CAAC;QACvB,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,aAAa,CAClB,mBAAmB,EACnB,YAAY,YAAY,mBAAmB,EAC3C,qDAAqD,CACtD,CAAC;QACJ,CAAC;QAED,IAAI,QAA8B,CAAC;QACnC,IAAI,CAAC;YACH,QAAQ,GAAG,WAAW,CAAC,YAAY,EAAE,SAAS,CAAC,CAAC;QAClD,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,GAAG,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YAC7D,OAAO,aAAa,CAAC,yBAAyB,EAAE,GAAG,CAAC,CAAC;QACvD,CAAC;QAED,IAAI,CAAC;YACH,QAAQ,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;QAC9B,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,aAAa,CAClB,gBAAgB,EAChB,SAAS,SAAS,2BAA2B,YAAY,IAAI,EAC7D,gDAAgD,CACjD,CAAC;QACJ,CAAC;QAED,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,YAAY,CAAC,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;YACzD,OAAO;gBACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;aAC3C,CAAC;QACJ,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,GAAG,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YAC7D,MAAM,CAAC,KAAK,CAAC,qBAAqB,EAAE;gBAClC,OAAO,EAAE,eAAe;gBACxB,IAAI,EAAE,SAAS;gBACf,OAAO,EAAE,YAAY;gBACrB,IAAI,EAAE,SAAS;gBACf,KAAK,EAAE,GAAG;aACX,CAAC,CAAC;YACH,OAAO,aAAa,CAAC,YAAY,EAAE,wBAAwB,GAAG,EAAE,CAAC,CAAC;QACpE,CAAC;IACH,CAAC,CACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* rename_file — rename or move a file within a project.
|
|
3
|
+
*/
|
|
4
|
+
import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
5
|
+
export declare const TOOL_NAME = "rename_file";
|
|
6
|
+
export declare function register(server: McpServer): void;
|
|
7
|
+
//# sourceMappingURL=rename-file.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rename-file.d.ts","sourceRoot":"","sources":["../../src/tools/rename-file.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAUzE,eAAO,MAAM,SAAS,gBAAgB,CAAC;AAMvC,wBAAgB,QAAQ,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CA0FhD"}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* rename_file — rename or move a file within a project.
|
|
3
|
+
*/
|
|
4
|
+
import { renameSync, statSync, mkdirSync, copyFileSync, unlinkSync } from 'fs';
|
|
5
|
+
import { join, dirname } from 'path';
|
|
6
|
+
import { getConfig } from '../config.js';
|
|
7
|
+
import { errorResponse } from '../utils/errors.js';
|
|
8
|
+
import { logger } from '../utils/logger.js';
|
|
9
|
+
import { resolveSafe } from '../utils/fs.js';
|
|
10
|
+
import { RenameFileSchema } from '../schemas/index.js';
|
|
11
|
+
export const TOOL_NAME = 'rename_file';
|
|
12
|
+
const DESCRIPTION = 'Rename or move a file within a Workday Studio project. ' +
|
|
13
|
+
'Creates parent directories for the destination if they do not exist.';
|
|
14
|
+
export function register(server) {
|
|
15
|
+
server.tool(TOOL_NAME, DESCRIPTION, RenameFileSchema.shape, async ({ project_name, old_path, new_path }) => {
|
|
16
|
+
const cfg = getConfig();
|
|
17
|
+
logger.info('Renaming project file', {
|
|
18
|
+
context: 'ToolExecution',
|
|
19
|
+
tool: TOOL_NAME,
|
|
20
|
+
project: project_name,
|
|
21
|
+
from: old_path,
|
|
22
|
+
to: new_path,
|
|
23
|
+
});
|
|
24
|
+
const projectDir = join(cfg.workspacePath, project_name);
|
|
25
|
+
try {
|
|
26
|
+
statSync(projectDir);
|
|
27
|
+
}
|
|
28
|
+
catch {
|
|
29
|
+
return errorResponse('PROJECT_NOT_FOUND', `Project '${project_name}' does not exist.`);
|
|
30
|
+
}
|
|
31
|
+
let src;
|
|
32
|
+
let dest;
|
|
33
|
+
try {
|
|
34
|
+
src = resolveSafe(project_name, old_path);
|
|
35
|
+
dest = resolveSafe(project_name, new_path);
|
|
36
|
+
}
|
|
37
|
+
catch (err) {
|
|
38
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
39
|
+
return errorResponse('PATH_TRAVERSAL_DETECTED', msg);
|
|
40
|
+
}
|
|
41
|
+
try {
|
|
42
|
+
statSync(src.absolute);
|
|
43
|
+
}
|
|
44
|
+
catch {
|
|
45
|
+
return errorResponse('FILE_NOT_FOUND', `Source file '${old_path}' does not exist in project '${project_name}'.`);
|
|
46
|
+
}
|
|
47
|
+
try {
|
|
48
|
+
statSync(dest.absolute);
|
|
49
|
+
return errorResponse('DEST_ALREADY_EXISTS', `Destination '${new_path}' already exists. Delete it first or choose a different name.`);
|
|
50
|
+
}
|
|
51
|
+
catch {
|
|
52
|
+
// Good — destination must not exist
|
|
53
|
+
}
|
|
54
|
+
try {
|
|
55
|
+
mkdirSync(dirname(dest.absolute), { recursive: true });
|
|
56
|
+
renameSync(src.absolute, dest.absolute);
|
|
57
|
+
}
|
|
58
|
+
catch {
|
|
59
|
+
// renameSync can fail across drives — fallback to copy+delete
|
|
60
|
+
try {
|
|
61
|
+
copyFileSync(src.absolute, dest.absolute);
|
|
62
|
+
unlinkSync(src.absolute);
|
|
63
|
+
}
|
|
64
|
+
catch (err2) {
|
|
65
|
+
const msg = err2 instanceof Error ? err2.message : String(err2);
|
|
66
|
+
return errorResponse('RENAME_FAILED', `Failed to rename file: ${msg}`);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
logger.debug('File renamed', {
|
|
70
|
+
context: 'ToolExecution',
|
|
71
|
+
tool: TOOL_NAME,
|
|
72
|
+
project: project_name,
|
|
73
|
+
from: old_path,
|
|
74
|
+
to: new_path,
|
|
75
|
+
});
|
|
76
|
+
return {
|
|
77
|
+
content: [
|
|
78
|
+
{
|
|
79
|
+
type: 'text',
|
|
80
|
+
text: JSON.stringify({ error: false, project: project_name, from: old_path, to: new_path }, null, 2),
|
|
81
|
+
},
|
|
82
|
+
],
|
|
83
|
+
};
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
//# sourceMappingURL=rename-file.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rename-file.js","sourceRoot":"","sources":["../../src/tools/rename-file.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* search_project_files — grep-style search across project files.
|
|
3
|
+
*/
|
|
4
|
+
import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
5
|
+
export declare const TOOL_NAME = "search_project_files";
|
|
6
|
+
export declare function register(server: McpServer): void;
|
|
7
|
+
//# sourceMappingURL=search-files.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"search-files.d.ts","sourceRoot":"","sources":["../../src/tools/search-files.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AASzE,eAAO,MAAM,SAAS,yBAAyB,CAAC;AAoChD,wBAAgB,QAAQ,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAyEhD"}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* search_project_files — grep-style search across project files.
|
|
3
|
+
*/
|
|
4
|
+
import { readFileSync, readdirSync, statSync } from 'fs';
|
|
5
|
+
import { join, relative } from 'path';
|
|
6
|
+
import { getConfig } from '../config.js';
|
|
7
|
+
import { errorResponse } from '../utils/errors.js';
|
|
8
|
+
import { logger } from '../utils/logger.js';
|
|
9
|
+
import { SearchFilesSchema } from '../schemas/index.js';
|
|
10
|
+
export const TOOL_NAME = 'search_project_files';
|
|
11
|
+
const DESCRIPTION = 'Search for a text pattern across all files in a Studio project. ' +
|
|
12
|
+
'Returns matching file paths with line numbers and the matched line content.';
|
|
13
|
+
function matchesGlob(filename, glob) {
|
|
14
|
+
const escaped = glob.replace(/[.+^${}()|[\]\\]/g, '\\$&').replace(/\*/g, '.*').replace(/\?/g, '.');
|
|
15
|
+
return new RegExp(`^${escaped}$`, 'i').test(filename);
|
|
16
|
+
}
|
|
17
|
+
function walk(dir, base, glob, results) {
|
|
18
|
+
let entries;
|
|
19
|
+
try {
|
|
20
|
+
entries = readdirSync(dir);
|
|
21
|
+
}
|
|
22
|
+
catch {
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
for (const e of entries) {
|
|
26
|
+
const full = join(dir, e);
|
|
27
|
+
let st;
|
|
28
|
+
try {
|
|
29
|
+
st = statSync(full);
|
|
30
|
+
}
|
|
31
|
+
catch {
|
|
32
|
+
continue;
|
|
33
|
+
}
|
|
34
|
+
if (st.isDirectory()) {
|
|
35
|
+
walk(full, base, glob, results);
|
|
36
|
+
}
|
|
37
|
+
else if (!glob || matchesGlob(e, glob)) {
|
|
38
|
+
results.push(full);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
export function register(server) {
|
|
43
|
+
server.tool(TOOL_NAME, DESCRIPTION, SearchFilesSchema.shape, async ({ project_name, pattern, file_glob }) => {
|
|
44
|
+
const cfg = getConfig();
|
|
45
|
+
logger.info('Searching project files', {
|
|
46
|
+
context: 'ToolExecution',
|
|
47
|
+
tool: TOOL_NAME,
|
|
48
|
+
project: project_name,
|
|
49
|
+
pattern,
|
|
50
|
+
});
|
|
51
|
+
const projectDir = join(cfg.workspacePath, project_name);
|
|
52
|
+
try {
|
|
53
|
+
statSync(projectDir);
|
|
54
|
+
}
|
|
55
|
+
catch {
|
|
56
|
+
return errorResponse('PROJECT_NOT_FOUND', `Project '${project_name}' does not exist.`, 'Use list_studio_projects to see available projects.');
|
|
57
|
+
}
|
|
58
|
+
let regex;
|
|
59
|
+
try {
|
|
60
|
+
regex = new RegExp(pattern, 'gi');
|
|
61
|
+
}
|
|
62
|
+
catch {
|
|
63
|
+
regex = new RegExp(pattern.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'), 'gi');
|
|
64
|
+
}
|
|
65
|
+
const filePaths = [];
|
|
66
|
+
walk(projectDir, projectDir, file_glob, filePaths);
|
|
67
|
+
const matches = [];
|
|
68
|
+
const MAX_MATCHES = 200;
|
|
69
|
+
for (const fp of filePaths) {
|
|
70
|
+
if (matches.length >= MAX_MATCHES)
|
|
71
|
+
break;
|
|
72
|
+
let text;
|
|
73
|
+
try {
|
|
74
|
+
text = readFileSync(fp, 'utf-8');
|
|
75
|
+
}
|
|
76
|
+
catch {
|
|
77
|
+
continue;
|
|
78
|
+
}
|
|
79
|
+
const lines = text.split('\n');
|
|
80
|
+
for (let i = 0; i < lines.length; i++) {
|
|
81
|
+
regex.lastIndex = 0;
|
|
82
|
+
if (regex.test(lines[i])) {
|
|
83
|
+
matches.push({
|
|
84
|
+
file: relative(projectDir, fp).replace(/\\/g, '/'),
|
|
85
|
+
line: i + 1,
|
|
86
|
+
text: lines[i].trim().slice(0, 300),
|
|
87
|
+
});
|
|
88
|
+
if (matches.length >= MAX_MATCHES)
|
|
89
|
+
break;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
return {
|
|
94
|
+
content: [
|
|
95
|
+
{
|
|
96
|
+
type: 'text',
|
|
97
|
+
text: JSON.stringify({
|
|
98
|
+
error: false,
|
|
99
|
+
project: project_name,
|
|
100
|
+
pattern,
|
|
101
|
+
match_count: matches.length,
|
|
102
|
+
truncated: matches.length >= MAX_MATCHES,
|
|
103
|
+
matches,
|
|
104
|
+
}, null, 2),
|
|
105
|
+
},
|
|
106
|
+
],
|
|
107
|
+
};
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
//# sourceMappingURL=search-files.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"search-files.js","sourceRoot":"","sources":["../../src/tools/search-files.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* validate_xml — validate XML syntax of a project file.
|
|
3
|
+
*/
|
|
4
|
+
import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
5
|
+
export declare const TOOL_NAME = "validate_xml";
|
|
6
|
+
export declare function register(server: McpServer): void;
|
|
7
|
+
//# sourceMappingURL=validate-xml.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validate-xml.d.ts","sourceRoot":"","sources":["../../src/tools/validate-xml.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAWzE,eAAO,MAAM,SAAS,iBAAiB,CAAC;AAMxC,wBAAgB,QAAQ,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAsEhD"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* validate_xml — validate XML syntax of a project file.
|
|
3
|
+
*/
|
|
4
|
+
import { readFileSync, statSync } from 'fs';
|
|
5
|
+
import { join } from 'path';
|
|
6
|
+
import { getConfig } from '../config.js';
|
|
7
|
+
import { errorResponse } from '../utils/errors.js';
|
|
8
|
+
import { logger } from '../utils/logger.js';
|
|
9
|
+
import { resolveSafe } from '../utils/fs.js';
|
|
10
|
+
import { validateXml } from '../utils/xml.js';
|
|
11
|
+
import { ValidateXmlSchema } from '../schemas/index.js';
|
|
12
|
+
export const TOOL_NAME = 'validate_xml';
|
|
13
|
+
const DESCRIPTION = 'Validate the XML syntax of a file in a Workday Studio project. ' +
|
|
14
|
+
'Returns validation status with any error details including line/column numbers.';
|
|
15
|
+
export function register(server) {
|
|
16
|
+
server.tool(TOOL_NAME, DESCRIPTION, ValidateXmlSchema.shape, async ({ project_name, file_path }) => {
|
|
17
|
+
const cfg = getConfig();
|
|
18
|
+
logger.info('Validating XML', {
|
|
19
|
+
context: 'ToolExecution',
|
|
20
|
+
tool: TOOL_NAME,
|
|
21
|
+
project: project_name,
|
|
22
|
+
file: file_path,
|
|
23
|
+
});
|
|
24
|
+
const projectDir = join(cfg.workspacePath, project_name);
|
|
25
|
+
try {
|
|
26
|
+
statSync(projectDir);
|
|
27
|
+
}
|
|
28
|
+
catch {
|
|
29
|
+
return errorResponse('PROJECT_NOT_FOUND', `Project '${project_name}' does not exist.`);
|
|
30
|
+
}
|
|
31
|
+
let resolved;
|
|
32
|
+
try {
|
|
33
|
+
resolved = resolveSafe(project_name, file_path);
|
|
34
|
+
}
|
|
35
|
+
catch (err) {
|
|
36
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
37
|
+
return errorResponse('PATH_TRAVERSAL_DETECTED', msg);
|
|
38
|
+
}
|
|
39
|
+
try {
|
|
40
|
+
statSync(resolved.absolute);
|
|
41
|
+
}
|
|
42
|
+
catch {
|
|
43
|
+
return errorResponse('FILE_NOT_FOUND', `File '${file_path}' not found in project '${project_name}'.`);
|
|
44
|
+
}
|
|
45
|
+
let content;
|
|
46
|
+
try {
|
|
47
|
+
content = readFileSync(resolved.absolute, 'utf-8');
|
|
48
|
+
}
|
|
49
|
+
catch (err) {
|
|
50
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
51
|
+
return errorResponse('READ_ERROR', `Failed to read file: ${msg}`);
|
|
52
|
+
}
|
|
53
|
+
const result = validateXml(content);
|
|
54
|
+
return {
|
|
55
|
+
content: [
|
|
56
|
+
{
|
|
57
|
+
type: 'text',
|
|
58
|
+
text: JSON.stringify({
|
|
59
|
+
error: false,
|
|
60
|
+
file: file_path,
|
|
61
|
+
valid: result.valid,
|
|
62
|
+
errors: result.errors,
|
|
63
|
+
}, null, 2),
|
|
64
|
+
},
|
|
65
|
+
],
|
|
66
|
+
};
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
//# sourceMappingURL=validate-xml.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validate-xml.js","sourceRoot":"","sources":["../../src/tools/validate-xml.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* workspace_tree — display a directory tree of a project or workspace.
|
|
3
|
+
*/
|
|
4
|
+
import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
5
|
+
export declare const TOOL_NAME = "workspace_tree";
|
|
6
|
+
export declare function register(server: McpServer): void;
|
|
7
|
+
//# sourceMappingURL=workspace-tree.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workspace-tree.d.ts","sourceRoot":"","sources":["../../src/tools/workspace-tree.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AASzE,eAAO,MAAM,SAAS,mBAAmB,CAAC;AA8C1C,wBAAgB,QAAQ,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CA8DhD"}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* workspace_tree — display a directory tree of a project or workspace.
|
|
3
|
+
*/
|
|
4
|
+
import { readdirSync, statSync } from 'fs';
|
|
5
|
+
import { join } from 'path';
|
|
6
|
+
import { getConfig } from '../config.js';
|
|
7
|
+
import { errorResponse } from '../utils/errors.js';
|
|
8
|
+
import { logger } from '../utils/logger.js';
|
|
9
|
+
import { WorkspaceTreeSchema } from '../schemas/index.js';
|
|
10
|
+
export const TOOL_NAME = 'workspace_tree';
|
|
11
|
+
const DESCRIPTION = 'Display a directory tree for one or all Workday Studio projects in the workspace.';
|
|
12
|
+
const DEFAULT_MAX_DEPTH = 4;
|
|
13
|
+
function buildTree(dir, depth, maxDepth, prefix, lines) {
|
|
14
|
+
if (depth > maxDepth)
|
|
15
|
+
return;
|
|
16
|
+
let entries;
|
|
17
|
+
try {
|
|
18
|
+
entries = readdirSync(dir).sort();
|
|
19
|
+
}
|
|
20
|
+
catch {
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
for (let i = 0; i < entries.length; i++) {
|
|
24
|
+
const name = entries[i];
|
|
25
|
+
if (name.startsWith('.'))
|
|
26
|
+
continue;
|
|
27
|
+
const isLast = i === entries.length - 1;
|
|
28
|
+
const connector = isLast ? '└── ' : '├── ';
|
|
29
|
+
const full = join(dir, name);
|
|
30
|
+
let isDir = false;
|
|
31
|
+
try {
|
|
32
|
+
isDir = statSync(full).isDirectory();
|
|
33
|
+
}
|
|
34
|
+
catch {
|
|
35
|
+
continue;
|
|
36
|
+
}
|
|
37
|
+
lines.push(prefix + connector + name + (isDir ? '/' : ''));
|
|
38
|
+
if (isDir) {
|
|
39
|
+
buildTree(full, depth + 1, maxDepth, prefix + (isLast ? ' ' : '│ '), lines);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
export function register(server) {
|
|
44
|
+
server.tool(TOOL_NAME, DESCRIPTION, WorkspaceTreeSchema.shape, async ({ project_name, max_depth }) => {
|
|
45
|
+
const cfg = getConfig();
|
|
46
|
+
const maxDepth = max_depth ?? DEFAULT_MAX_DEPTH;
|
|
47
|
+
logger.info('Building workspace tree', {
|
|
48
|
+
context: 'ToolExecution',
|
|
49
|
+
tool: TOOL_NAME,
|
|
50
|
+
project: project_name ?? '(all)',
|
|
51
|
+
maxDepth,
|
|
52
|
+
});
|
|
53
|
+
if (project_name) {
|
|
54
|
+
const projectDir = join(cfg.workspacePath, project_name);
|
|
55
|
+
try {
|
|
56
|
+
statSync(projectDir);
|
|
57
|
+
}
|
|
58
|
+
catch {
|
|
59
|
+
return errorResponse('PROJECT_NOT_FOUND', `Project '${project_name}' does not exist.`);
|
|
60
|
+
}
|
|
61
|
+
const lines = [project_name + '/'];
|
|
62
|
+
buildTree(projectDir, 1, maxDepth, '', lines);
|
|
63
|
+
return { content: [{ type: 'text', text: lines.join('\n') }] };
|
|
64
|
+
}
|
|
65
|
+
// All projects
|
|
66
|
+
let projects;
|
|
67
|
+
try {
|
|
68
|
+
projects = readdirSync(cfg.workspacePath)
|
|
69
|
+
.filter((n) => {
|
|
70
|
+
try {
|
|
71
|
+
return statSync(join(cfg.workspacePath, n)).isDirectory() && !n.startsWith('.');
|
|
72
|
+
}
|
|
73
|
+
catch {
|
|
74
|
+
return false;
|
|
75
|
+
}
|
|
76
|
+
})
|
|
77
|
+
.sort();
|
|
78
|
+
}
|
|
79
|
+
catch (err) {
|
|
80
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
81
|
+
return errorResponse('READ_ERROR', `Failed to read workspace: ${msg}`);
|
|
82
|
+
}
|
|
83
|
+
const lines = [cfg.workspacePath + '/'];
|
|
84
|
+
for (let i = 0; i < projects.length; i++) {
|
|
85
|
+
const name = projects[i];
|
|
86
|
+
const isLast = i === projects.length - 1;
|
|
87
|
+
lines.push((isLast ? '└── ' : '├── ') + name + '/');
|
|
88
|
+
buildTree(join(cfg.workspacePath, name), 1, maxDepth - 1, isLast ? ' ' : '│ ', lines);
|
|
89
|
+
}
|
|
90
|
+
return { content: [{ type: 'text', text: lines.join('\n') }] };
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
//# sourceMappingURL=workspace-tree.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workspace-tree.js","sourceRoot":"","sources":["../../src/tools/workspace-tree.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* write_project_file — write (create or overwrite) a project file with optional backup.
|
|
3
|
+
*/
|
|
4
|
+
import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
5
|
+
export declare const TOOL_NAME = "write_project_file";
|
|
6
|
+
export declare function register(server: McpServer): void;
|
|
7
|
+
//# sourceMappingURL=write-file.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"write-file.d.ts","sourceRoot":"","sources":["../../src/tools/write-file.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAUzE,eAAO,MAAM,SAAS,uBAAuB,CAAC;AAM9C,wBAAgB,QAAQ,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAkFhD"}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* write_project_file — write (create or overwrite) a project file with optional backup.
|
|
3
|
+
*/
|
|
4
|
+
import { writeFileSync, copyFileSync, statSync, mkdirSync } from 'fs';
|
|
5
|
+
import { join, dirname } from 'path';
|
|
6
|
+
import { getConfig } from '../config.js';
|
|
7
|
+
import { errorResponse } from '../utils/errors.js';
|
|
8
|
+
import { logger } from '../utils/logger.js';
|
|
9
|
+
import { resolveSafe } from '../utils/fs.js';
|
|
10
|
+
import { WriteFileSchema } from '../schemas/index.js';
|
|
11
|
+
export const TOOL_NAME = 'write_project_file';
|
|
12
|
+
const DESCRIPTION = 'Write content to a file in a Workday Studio project. ' +
|
|
13
|
+
'Creates parent directories if needed. Optionally creates a .bak backup before overwriting.';
|
|
14
|
+
export function register(server) {
|
|
15
|
+
server.tool(TOOL_NAME, DESCRIPTION, WriteFileSchema.shape, async ({ project_name, file_path, content, create_backup }) => {
|
|
16
|
+
const cfg = getConfig();
|
|
17
|
+
const shouldBackup = create_backup ?? cfg.backupOnWrite;
|
|
18
|
+
logger.info('Writing project file', {
|
|
19
|
+
context: 'ToolExecution',
|
|
20
|
+
tool: TOOL_NAME,
|
|
21
|
+
project: project_name,
|
|
22
|
+
file: file_path,
|
|
23
|
+
backup: shouldBackup,
|
|
24
|
+
});
|
|
25
|
+
const projectDir = join(cfg.workspacePath, project_name);
|
|
26
|
+
try {
|
|
27
|
+
statSync(projectDir);
|
|
28
|
+
}
|
|
29
|
+
catch {
|
|
30
|
+
return errorResponse('PROJECT_NOT_FOUND', `Project '${project_name}' does not exist.`, 'Use list_studio_projects to see available projects.');
|
|
31
|
+
}
|
|
32
|
+
let resolved;
|
|
33
|
+
try {
|
|
34
|
+
resolved = resolveSafe(project_name, file_path);
|
|
35
|
+
}
|
|
36
|
+
catch (err) {
|
|
37
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
38
|
+
return errorResponse('PATH_TRAVERSAL_DETECTED', msg);
|
|
39
|
+
}
|
|
40
|
+
let backedUp = false;
|
|
41
|
+
if (shouldBackup) {
|
|
42
|
+
try {
|
|
43
|
+
statSync(resolved.absolute);
|
|
44
|
+
copyFileSync(resolved.absolute, resolved.absolute + '.bak');
|
|
45
|
+
backedUp = true;
|
|
46
|
+
}
|
|
47
|
+
catch {
|
|
48
|
+
// File doesn't exist yet — no backup needed
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
try {
|
|
52
|
+
mkdirSync(dirname(resolved.absolute), { recursive: true });
|
|
53
|
+
writeFileSync(resolved.absolute, content, 'utf-8');
|
|
54
|
+
logger.debug('File written successfully', {
|
|
55
|
+
context: 'ToolExecution',
|
|
56
|
+
tool: TOOL_NAME,
|
|
57
|
+
project: project_name,
|
|
58
|
+
file: file_path,
|
|
59
|
+
});
|
|
60
|
+
return {
|
|
61
|
+
content: [
|
|
62
|
+
{
|
|
63
|
+
type: 'text',
|
|
64
|
+
text: JSON.stringify({
|
|
65
|
+
error: false,
|
|
66
|
+
written: file_path,
|
|
67
|
+
backed_up: backedUp,
|
|
68
|
+
backup_path: backedUp ? file_path + '.bak' : null,
|
|
69
|
+
}, null, 2),
|
|
70
|
+
},
|
|
71
|
+
],
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
catch (err) {
|
|
75
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
76
|
+
logger.error('Failed to write file', {
|
|
77
|
+
context: 'ToolExecution',
|
|
78
|
+
tool: TOOL_NAME,
|
|
79
|
+
project: project_name,
|
|
80
|
+
file: file_path,
|
|
81
|
+
error: msg,
|
|
82
|
+
});
|
|
83
|
+
return errorResponse('WRITE_FAILED', `Failed to write file: ${msg}`);
|
|
84
|
+
}
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
//# sourceMappingURL=write-file.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"write-file.js","sourceRoot":"","sources":["../../src/tools/write-file.ts"],"names":[],"mappings":"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"}
|