项目管理服务

MCP服务器为Wethod项目管理提供时间表、计划、预算和团队工具。

  • by cesconix
  • TypeScript
  • 本地部署
  • 更新于
在 GitHub 查看 cesconix/mcp-wethod

使用说明

mcp天气

MCP服务器 Wethod 项目管理——时间表、计划、预算和团队工具。

安装

claude mcp add wethod -- npx mcp-wethod

首次使用时 setup 该工具指导您完成交互式配置:公司段塞、API令牌和SF6SESSID cookie。凭据存储在 ~/.mcp-wethod/config.json.

对于CI或脚本设置,传递所有三个环境变量以跳过交互式设置:

claude mcp add wethod \
  -e WETHOD_COMPANY=your-company \
  -e WETHOD_API_TOKEN=your-token \
  -e WETHOD_PERSON_ID=your-person-id \
  -- npx mcp-wethod

环境变量

当所有三个都设置好时,环境变量将覆盖 config.json.

变量 描述
WETHOD_COMPANY 公司蛞蝓(之前的部分 .wethod.com)
WETHOD_API_TOKEN Wethod API身份验证的承载令牌
WETHOD_PERSON_ID 您在Wethod中的个人ID

工具(33)

配置

工具 说明
setup 两步入职:提供凭据和同步数据(step=credentials),然后设置您的个人ID(step=identify)
reset 删除所有本地数据和配置,从头开始安装

工时表

工具 描述 端点
list_timesheets 列出人员的时间表条目,并带有可选的项目/日期筛选器 GET /api/timesheets
create_timesheet 创建新的时间表条目(验证每天8小时的限制) GET /api/timesheets POST /api/timesheets
update_timesheet 更新现有时间表条目的小时数或备注 PATCH /api/timesheets/:id
delete_timesheet 按ID删除时间表条目 DELETE /api/timesheets/:id
check_timesheet_status 检查给定一周内某人的时间表完整性 GET /api/timesheets
list_timesheet_logs 列出时间表更改日志以供审核 GET /api/timesheet-logs

分配

工具 描述 端点
list_allocations 列出人员分配,并使用人员、项目和日期范围的筛选器 GET /api/people-allocations
create_allocation 创建分配条目(周一至周五为工作日的单个日期或日期范围,验证每天8小时的限制) POST /api/people-allocations
update_allocation 按ID更新现有分配的小时数 PATCH /api/people-allocations/:id
delete_allocation 删除分配条目(按ID单个或按日期范围,可选按项目筛选) DELETE /api/people-allocations/:id

团队与规划

工具 描述 端点
get_team_timesheet 检查多人的时间表完成状态 GET /api/timesheets
get_weekly_plan 根据分配数据显示本周谁在做什么 GET /api/people-allocations
get_availability 显示每人的利用率和可用容量 GET /api/people-allocations

报告

工具 描述 端点
get_billability_report 计算一个日期范围内多个人的计费百分比 GET /api/timesheets

项目

工具 描述 端点
list_projects 按概率和分页筛选列出项目 GET /api/projects
get_project 按ID获取单个项目的完整详细信息 GET /api/projects/:id
list_budgets 列出项目预算,包括状态、天数、成本和价格 GET /api/budgets
list_productions 按项目和日期列出实际生产值 GET /api/productions
list_production_plans 列出计划生产值以进行差异跟踪 GET /api/production-plans

项目状态

工具 描述 端点
list_project_statuses 列出每周项目状态,可按项目筛选 GET /api/project-statuses
get_project_status 按ID获取单个项目状态的完整详细信息 GET /api/project-statuses/:id
create_project_status 创建每周状态(剩余天数模式); days_left 根据预算-时间表明确或自动计算;需要 confirm GET /api/budgets GET /api/timesheets POST /api/project-statuses
delete_project_status 按ID删除项目状态(更正按删除+创建完成) DELETE /api/project-statuses/:id
backfill_project_statuses 在周一范围内回填每周状态;默认情况下进行模拟运行,跳过或覆盖现有 GET /api/budgets GET /api/timesheets GET/POST/DELETE /api/project-statuses

客户与产能

工具 描述 端点
list_clients 列出客户及其公司名称、联系人和详细信息 GET /api/clients
list_capacities 列出工作能力配置和每周时间表 GET /api/capacities

查找

工具 描述 来源
lookup_person 从本地同步数据中按ID或姓名查找人员 persons.json
lookup_project 从本地同步数据中按ID或名称查找项目 projects.json
lookup_client 从本地同步数据中按ID或名称查找客户端 clients.json
lookup_project_type 从本地同步数据中按ID或名称查找项目类型 project-types.json

同步

工具 描述 端点
sync 获取人员、项目、客户和项目类型(需要SF6SESSID会话cookie) GET /report/timetracking GET /api/clients GET /api/projects

提示(2)

提示 描述
timesheet_reminder 检查团队时间表状态并生成友好提醒
weekly_summary 生成团队活动和项目状态的每周摘要

数据同步

这 sync 该工具从Wethod API获取参考数据(人员、项目、客户端),并编写本地JSON缓存文件。这些文件由 lookup_* 用于快速离线查找的工具。

数据存储在:

~/.mcp-wethod/
├── config.json
├── persons.json
├── projects.json
├── clients.json
└── project-types.json

跑 sync 在使用查找工具之前一次,并定期保持缓存新鲜。

获取会话ID

这 sync 工具需要 SF6SESSID 用于访问时间跟踪报告的cookie。要检索它,请执行以下操作:

  1. 打开浏览器并登录Wethod
  2. 打开DevTools(F12或Cmd+Opt+I)
  3. 首选 应用 → 饼干 → api.wethod.com
  4. 复制的值 SF6SESSID 曲奇
  5. 当Claude要求提供会话ID时,粘贴该值

会话ID会定期过期——到期时需要检索一个新的会话ID。

多实例

要连接到多个Wethod公司,请使用环境变量注册单独的MCP实例:

claude mcp add wethod-acme \
  -e WETHOD_COMPANY=acme \
  -e WETHOD_API_TOKEN=token-for-acme \
  -e WETHOD_PERSON_ID=person-id-for-acme \
  -- npx mcp-wethod

claude mcp add wethod-globex \
  -e WETHOD_COMPANY=globex \
  -e WETHOD_API_TOKEN=token-for-globex \
  -e WETHOD_PERSON_ID=person-id-for-globex \
  -- npx mcp-wethod

发展

pnpm install          # Install dependencies
pnpm run lint         # Lint and format check (Biome)
pnpm run format       # Auto-fix lint and formatting
pnpm run typecheck    # Type-check (tsc --noEmit)
pnpm run test         # Run tests (Vitest)
pnpm run build        # Build (tsc)

需要Node.js>=22。

编写工具

每个工具下都有一个文件 src/tools/<domain>/ 出口a register<Name> 功能和遵循相同的形状。典型示例: projects/list-budgets.mts (阅读)和 timesheet/delete-timesheet.mts (删除)。

习俗:

  • 域文件夹 --工具按域分组: timesheet/, allocations/, planning/, reporting/, projects/, project-status/, reference/, lookup/, system/。将文件放入其域的文件夹中。共享 助手留在家里 src/utils/ --域文件夹不包含自己的utils。
  • 文件名(&N) --烤肉串案件档案 foo-bar.mts 出口 registerFooBar MCP工具名称为snake_case foo_bar;标题是标题案例。
  • 第二个arg — client: WethodClient 对于API工具, data: DataLoader 为了 当工具解析名称时,可以执行本地数据查找或两者兼而有之。
  • 输入架构 --内联zod字段。传播 paginationSchema (从 utils/schemas.mjs)for limit/offset 而不是重新声明它们。
  • 注释 — READONLY_ANNOTATIONS / WRITE_ANNOTATIONS / DELETE_ANNOTATIONS 从 utils/constants.mjs.
  • 域名类型 --进口自 utils/schemas.mjs;永远不要重新声明回复 形状内联。对于读取工具,请将模式传递给 client.request({ schema }) 因此改变的API表面上是一个巨大的错误。
  • 输出 --返回 textResult(text) 为了成功和 errorText(text) 为了一个 处理程序验证失败;把身体裹起来 try/catch 返回 formatToolError(error).Gate使用 requireConfirm(params.confirm).
import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"
import { z } from "zod"
import type { WethodClient } from "../../utils/client.mjs"
import { READONLY_ANNOTATIONS } from "../../utils/constants.mjs"
import { formatToolError, textResult } from "../../utils/format.mjs"
import { BudgetSchema, paginationSchema } from "../../utils/schemas.mjs"

export function registerListExample(server: McpServer, client: WethodClient) {
  server.registerTool(
    "list_example",
    {
      title: "List Example",
      description: "Plain-English description shown to the LLM; say what it returns.",
      inputSchema: {
        ...paginationSchema,
        project_id: z.number().int().optional().describe("Filter by project ID"),
        // write/delete tools also add: confirm: z.boolean().describe("Must be true ...")
      },
      annotations: READONLY_ANNOTATIONS,
    },
    async (params) => {
      try {
        // write/delete tools first: const gate = requireConfirm(params.confirm); if (gate) return gate
        const rows = await client.request("GET", "/api/example", {
          params: { limit: params.limit, offset: params.offset, project_id: params.project_id },
          schema: z.array(BudgetSchema),
        })
        if (rows.length === 0) return textResult("No examples found.")
        const lines = rows.map((r) => `id: ${r.id} | Project ${r.project_id}`)
        return textResult(`Found ${rows.length} example(s):\n\n${lines.join("\n")}`)
      } catch (error) {
        return formatToolError(error)
      }
    },
  )
}

异常:纯内存查找工具(无I/O)故意省略 try/catch --看 lookup/lookup-person.mts.

许可证

麻省理工学院