targetprocess-mcp-server 2.2.2 → 2.2.3-a

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/build/index.js CHANGED
@@ -1,11 +1,10 @@
1
1
  #!/usr/bin/env node
2
- import { execSync } from "child_process";
3
- import { homedir } from "os";
4
2
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
5
3
  import { z } from "zod";
6
4
  import { JSDOM } from "jsdom";
7
5
  import { TpClient } from "./tp.js";
8
6
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
7
+ import { config } from "./config.js";
9
8
  const server = new McpServer({
10
9
  name: "tp",
11
10
  version: "1.0.0"
@@ -376,6 +375,7 @@ server.registerTool('search_tp_cards', {
376
375
  title: item.Name,
377
376
  id: item.Id,
378
377
  description: descriptionText,
378
+ url: `${config.tp.url}/entity/${item.Id}`,
379
379
  };
380
380
  });
381
381
  return {
@@ -1240,92 +1240,6 @@ server.registerTool('add_test_cases_to_test_plan', {
1240
1240
  }]
1241
1241
  };
1242
1242
  });
1243
- server.registerTool('add_attached_file_to_card', {
1244
- title: 'Attach a file to a TP card',
1245
- description: 'Upload and attach a local file to a Targetprocess entity (UserStory, Bug, Feature, etc.) by its ID',
1246
- inputSchema: {
1247
- generalId: z.string()
1248
- .min(5)
1249
- .max(6)
1250
- .describe('TP entity ID to attach the file to (e.g. 145789)'),
1251
- filePath: z.string()
1252
- .describe('Absolute path to the local file to upload (e.g. /Users/mcs/Desktop/image.png)'),
1253
- },
1254
- }, async ({ generalId, filePath }) => {
1255
- try {
1256
- const result = await tp.addAttachedFile(generalId, filePath);
1257
- if (!result) {
1258
- return {
1259
- content: [{
1260
- type: 'text',
1261
- text: `Failed to attach file "${filePath}" to card id: ${generalId}`
1262
- }]
1263
- };
1264
- }
1265
- return {
1266
- content: [{
1267
- type: 'text',
1268
- text: result
1269
- }]
1270
- };
1271
- }
1272
- catch (error) {
1273
- return {
1274
- content: [{
1275
- type: 'text',
1276
- text: `Error attaching file to card ${generalId}: ${error}`
1277
- }]
1278
- };
1279
- }
1280
- });
1281
- server.registerTool('find_file_on_disk', {
1282
- title: 'Find a file on disk by name',
1283
- description: `Search for a file by name on the local filesystem.
1284
- First tries an exact (case-insensitive) match.
1285
- If nothing is found, retries using the first half of the filename (without extension) as a wildcard — e.g. "screenshot_bug" becomes "*screensho*".
1286
- Returns a list of matching absolute paths.`,
1287
- inputSchema: {
1288
- fileName: z.string()
1289
- .describe('Filename to search for, with or without extension (e.g. "screenshot.png" or "report")'),
1290
- searchDir: z.string()
1291
- .optional()
1292
- .describe('Directory to search in — defaults to the user home directory'),
1293
- },
1294
- }, async ({ fileName, searchDir }) => {
1295
- const dir = searchDir || homedir();
1296
- const runFind = (pattern) => {
1297
- try {
1298
- const out = execSync(`find "${dir}" -iname "${pattern}" 2>/dev/null`, {
1299
- encoding: 'utf8',
1300
- timeout: 15000,
1301
- });
1302
- return out.trim().split('\n').filter(Boolean);
1303
- }
1304
- catch {
1305
- return [];
1306
- }
1307
- };
1308
- // Exact match
1309
- let files = runFind(fileName);
1310
- if (files.length > 0) {
1311
- return {
1312
- content: [{ type: 'text', text: JSON.stringify({ match: 'exact', files }) }]
1313
- };
1314
- }
1315
- // Partial match: first half of name without extension
1316
- const dotIndex = fileName.lastIndexOf('.');
1317
- const nameOnly = dotIndex > 0 ? fileName.slice(0, dotIndex) : fileName;
1318
- const half = nameOnly.slice(0, Math.ceil(nameOnly.length / 2));
1319
- files = runFind(`*${half}*`);
1320
- if (files.length > 0) {
1321
- return {
1322
- content: [{ type: 'text', text: JSON.stringify({ match: 'partial', keyword: half, files }) }]
1323
- };
1324
- }
1325
- return {
1326
- content: [{ type: 'text', text: `No files found matching "${fileName}" or partial keyword "${half}" in ${dir}` }]
1327
- };
1328
- });
1329
1243
  async function main() {
1330
1244
  const transport = new StdioServerTransport();
1331
1245
  await server.connect(transport);
package/build/tp.js CHANGED
@@ -493,13 +493,22 @@ export class TpClient {
493
493
  param: { "format": "json", }
494
494
  });
495
495
  }
496
- async addAttachedFile(generalId, filePath) {
497
- const fileContent = readFileSync(filePath);
498
- const fileName = basename(filePath);
496
+ async addAttachedFile(generalId, source) {
497
+ let blob;
498
+ let fileName;
499
+ if ("filePath" in source) {
500
+ blob = new Blob([readFileSync(source.filePath)]);
501
+ fileName = basename(source.filePath);
502
+ }
503
+ else {
504
+ blob = new Blob([Buffer.from(source.fileContent, "base64")]);
505
+ fileName = source.fileName;
506
+ }
499
507
  const formData = new FormData();
500
508
  formData.append("generalId", generalId);
501
- formData.append("file", new Blob([fileContent]), fileName);
509
+ formData.append("file", blob, fileName);
502
510
  const url = `${this.baseUrl}/UploadFile.ashx?access_token=${this.token}`;
511
+ console.error(JSON.stringify({ "UPLOAD_URL": url.replace(this.token, "***") }, null, 2));
503
512
  try {
504
513
  const response = await fetch(url, {
505
514
  method: "POST",
@@ -508,7 +517,7 @@ export class TpClient {
508
517
  if (!response.ok) {
509
518
  throw new Error(`HTTP error! status: ${response.status}`);
510
519
  }
511
- return response.text();
520
+ return await response.text();
512
521
  }
513
522
  catch (error) {
514
523
  console.error("Error uploading file:", error);
package/package.json CHANGED
@@ -25,7 +25,7 @@
25
25
  "engines": {
26
26
  "node": ">=20.x"
27
27
  },
28
- "version": "2.2.2",
28
+ "version": "2.2.3a",
29
29
  "description": "MCP server for Tartget Process",
30
30
  "main": "build/index.js",
31
31
  "keywords": [