Method CRM MCP by usefulapi

Query Method CRM customers, leads, activities and invoices; create and update records.

我该使用它吗

质量与安全性

A
描述质量
100%
模式完整度
88%
命名质量
80%
投毒风险
100%
权限匹配度
100%
协议合规性
100%

基于对工具定义和协议合规性的自动分析。

上下文开销

~5,181token 数(工具定义)
~2.2 KB典型响应大小
对注意力有显著影响(占 128k 上下文窗口的 4.05%)

这是每次将服务器的工具加载到模型上下文窗口时所消耗的大致 token 数。数值越高,可用于其他任务的注意力就越少。

安装

一键安装

将以下内容添加到你的 `claude_desktop_config.json` 文件中:

{
  "mcpServers": {
    "method-crm": {
      "url": "https://method-crm.usefulapi.io/mcp"
    }
  }
}

远程端点

https://method-crm.usefulapi.io/mcpstreamable-http

它能做什么

工具清单

工具(16)

🟢 只读🟡 写入🔴 删除⚪ 未知
🟢method_get_account

Who the API key acts as: the Method user behind it (id and name; use the id as an assignee). Also a cheap check that the key works. GET /api/v1/me.

输入模式

{
  "type": "object",
  "properties": {},
  "$schema": "https://json-schema.org/draft/2020-12/schema"
}
🟢method_list_tables

List every table on this Method account (standard QuickBooks/Xero/Method tables and custom ones) with its source and whether it can be created, updated or deleted. Tables differ per account: call this before querying a table you are unsure of. GET /api/v1/tables.

输入模式

{
  "type": "object",
  "properties": {},
  "$schema": "https://json-schema.org/draft/2020-12/schema"
}
🟢method_get_table_fields(table)

The exact field names of a table with type, whether required, creatable and mutable, and for dropdowns the table they reference. Use it to pick `select` fields and to name fields in create/update calls (names are case-sensitive and wrong ones are silently ignored). GET /api/v1/tables/{table}/fields.

输入模式

{
  "type": "object",
  "properties": {
    "table": {
      "type": "string",
      "pattern": "^[A-Za-z][A-Za-z0-9_]{0,63}$",
      "description": "Table name exactly as method_list_tables shows it, e.g. Customer, Contacts, Activity, Invoice, Estimate."
    }
  },
  "required": [
    "table"
  ],
  "$schema": "https://json-schema.org/draft/2020-12/schema"
}
🟢method_query_records(table, select, filter, orderby, apply, ...)

Query any table (Customer, Contacts, Activity, Invoice, Estimate, Item, Users, custom tables ...). Always pass `select`. `filter` uses OData-style syntax: strings in single quotes, dates as '2026-05-26T00:00:00Z' with Z or an offset, operators eq ne lt gt le ge and or not, functions contains(Name,'x') startswith() endswith(); e.g. "BalanceRemaining gt 0 and DueDate lt '2026-10-01T00:00:00Z'". `apply` runs server-side aggregation instead of listing rows, e.g. "aggregate(BalanceRemaining with sum as Outstanding)" or "groupby((Customer), aggregate(Amount with sum as Total))". Default order is RecordID ascending (stable paging); page with next_skip. GET /api/v1/tables/{table}.

输入模式

{
  "type": "object",
  "properties": {
    "table": {
      "type": "string",
      "pattern": "^[A-Za-z][A-Za-z0-9_]{0,63}$",
      "description": "Table name exactly as method_list_tables shows it, e.g. Customer, Contacts, Activity, Invoice, Estimate."
    },
    "select": {
      "minItems": 1,
      "maxItems": 60,
      "type": "array",
      "items": {
        "type": "string",
        "pattern": "^[A-Za-z][A-Za-z0-9_]{0,63}$"
      },
      "description": "Field names to return (case-sensitive, from method_get_table_fields). Without a select Method returns hundreds of columns per row."
    },
    "filter": {
      "description": "Filter expression, e.g. \"IsLeadStatusOnly eq true and contains(Name,'Smith')\".",
      "type": "string",
      "minLength": 1,
      "maxLength": 1500
    },
    "orderby": {
      "description": "Sort, e.g. \"RecordID desc\" or \"TotalBalance desc,RecordID\".",
      "type": "string",
      "minLength": 1,
      "maxLength": 300,
      "pattern": "^[A-Za-z0-9_, ]+$"
    },
    "apply": {
      "description": "Aggregation, e.g. \"aggregate($count as Total)\"; ignores paging.",
      "type": "string",
      "minLength": 1,
      "maxLength": 1500
    },
    "top": {
      "description": "Rows per page, 1-100 (default 25).",
      "type": "integer",
      "exclusiveMinimum": 0,
      "maximum": 100
    },
    "skip": {
      "description": "Rows to skip (default 0). Pass the previous reply's next_skip.",
      "type": "integer",
      "minimum": 0,
      "maximum": 10000000
    }
  },
  "required": [
    "table"
  ],
  "$schema": "https://json-schema.org/draft/2020-12/schema"
}
🟢method_count_records(table, filter)

How many records a table has, optionally matching a filter (same filter syntax as method_query_records). Cheap: call it before paging through a big table. GET /api/v1/tables/{table}/count.

输入模式

{
  "type": "object",
  "properties": {
    "table": {
      "type": "string",
      "pattern": "^[A-Za-z][A-Za-z0-9_]{0,63}$",
      "description": "Table name exactly as method_list_tables shows it, e.g. Customer, Contacts, Activity, Invoice, Estimate."
    },
    "filter": {
      "description": "Filter expression.",
      "type": "string",
      "minLength": 1,
      "maxLength": 1500
    }
  },
  "required": [
    "table"
  ],
  "$schema": "https://json-schema.org/draft/2020-12/schema"
}
🟢method_get_record(table, record_id, select, expand)

One record by RecordID from any table. Pass `select` to limit the columns; `expand` names a related CHILD table whose rows are embedded (e.g. InvoiceLine on Invoice; at most 50 rows); a parent such as a contact's Entity is not expanded: read it with its own RecordID (Entity_RecordID). GET /api/v1/tables/{table}/{recordId}.

输入模式

{
  "type": "object",
  "properties": {
    "table": {
      "type": "string",
      "pattern": "^[A-Za-z][A-Za-z0-9_]{0,63}$",
      "description": "Table name exactly as method_list_tables shows it, e.g. Customer, Contacts, Activity, Invoice, Estimate."
    },
    "record_id": {
      "type": "integer",
      "exclusiveMinimum": 0,
      "maximum": 2147483647,
      "description": "The record's RecordID."
    },
    "select": {
      "minItems": 1,
      "maxItems": 60,
      "type": "array",
      "items": {
        "type": "string",
        "pattern": "^[A-Za-z][A-Za-z0-9_]{0,63}$"
      },
      "description": "Field names to return (case-sensitive, from method_get_table_fields). Without a select Method returns hundreds of columns per row."
    },
    "expand": {
      "description": "A child table to embed (a table with a dropdown field to this one), e.g. InvoiceLine on Invoice. At most 50 child rows.",
      "type": "string",
      "pattern": "^[A-Za-z][A-Za-z0-9_]{0,63}$"
    }
  },
  "required": [
    "table",
    "record_id"
  ],
  "$schema": "https://json-schema.org/draft/2020-12/schema"
}
🟢method_search_customers(text, kind, active_only, select, top, ...)

Find customers and leads (the Customer table: Customers & Leads in Method) by text in the name or email, by lead/customer type, or list them all. Returns RecordID, name, email, phone, lead flag and status; override `select` for other fields (see method_get_table_fields with table Customer). Page with next_skip. GET /api/v1/tables/Customer.

输入模式

{
  "type": "object",
  "properties": {
    "text": {
      "description": "Matches records whose Name or Email contains this text (case-insensitive).",
      "type": "string",
      "minLength": 1,
      "maxLength": 200
    },
    "kind": {
      "description": "leads = IsLeadStatusOnly true, customers = false (default all).",
      "type": "string",
      "enum": [
        "all",
        "leads",
        "customers"
      ]
    },
    "active_only": {
      "description": "Only active records (IsActive true).",
      "type": "boolean"
    },
    "select": {
      "minItems": 1,
      "maxItems": 60,
      "type": "array",
      "items": {
        "type": "string",
        "pattern": "^[A-Za-z][A-Za-z0-9_]{0,63}$"
      },
      "description": "Field names to return (case-sensitive, from method_get_table_fields). Without a select Method returns hundreds of columns per row."
    },
    "top": {
      "description": "Rows per page, 1-100 (default 25).",
      "type": "integer",
      "exclusiveMinimum": 0,
      "maximum": 100
    },
    "skip": {
      "description": "Rows to skip (default 0). Pass the previous reply's next_skip.",
      "type": "integer",
      "minimum": 0,
      "maximum": 10000000
    }
  },
  "$schema": "https://json-schema.org/draft/2020-12/schema"
}
🟢method_list_contacts(entity_id, text, select, top, skip)

List contacts (people), optionally those of one customer/lead entity (entity_id = the Customer's RecordID) or matching text in name/email/phone. Returns RecordID, name, email, phone, the entity link and active flag. Use a Contact's RecordID (not the Customer's) when linking activities. GET /api/v1/tables/Contacts.

输入模式

{
  "type": "object",
  "properties": {
    "entity_id": {
      "description": "Only contacts of this entity (the Customer/Vendor RecordID).",
      "type": "integer",
      "exclusiveMinimum": 0,
      "maximum": 2147483647
    },
    "text": {
      "description": "Matches contacts whose Name, Email or Phone contains this text.",
      "type": "string",
      "minLength": 1,
      "maxLength": 200
    },
    "select": {
      "minItems": 1,
      "maxItems": 60,
      "type": "array",
      "items": {
        "type": "string",
        "pattern": "^[A-Za-z][A-Za-z0-9_]{0,63}$"
      },
      "description": "Field names to return (case-sensitive, from method_get_table_fields). Without a select Method returns hundreds of columns per row."
    },
    "top": {
      "description": "Rows per page, 1-100 (default 25).",
      "type": "integer",
      "exclusiveMinimum": 0,
      "maximum": 100
    },
    "skip": {
      "description": "Rows to skip (default 0). Pass the previous reply's next_skip.",
      "type": "integer",
      "minimum": 0,
      "maximum": 10000000
    }
  },
  "$schema": "https://json-schema.org/draft/2020-12/schema"
}
🟢method_list_activities(entity_id, assigned_to_id, due_after, due_before, select, ...)

List activities (calls, emails, to-dos, notes), newest first. Filter by the entity they belong to, the assigned user or a due-date window. The note text is in Comments. Override `select` for other fields (method_get_table_fields with table Activity). GET /api/v1/tables/Activity.

输入模式

{
  "type": "object",
  "properties": {
    "entity_id": {
      "description": "Only activities of this entity (Customer RecordID).",
      "type": "integer",
      "exclusiveMinimum": 0,
      "maximum": 2147483647
    },
    "assigned_to_id": {
      "description": "Only activities assigned to this user id (method_get_account or the Users table).",
      "type": "integer",
      "exclusiveMinimum": 0,
      "maximum": 2147483647
    },
    "due_after": {
      "type": "string",
      "description": "ISO 8601 date-time WITH a timezone (Z or +hh:mm), e.g. 2026-10-01T00:00:00Z."
    },
    "due_before": {
      "type": "string",
      "description": "ISO 8601 date-time WITH a timezone (Z or +hh:mm), e.g. 2026-10-01T00:00:00Z."
    },
    "select": {
      "minItems": 1,
      "maxItems": 60,
      "type": "array",
      "items": {
        "type": "string",
        "pattern": "^[A-Za-z][A-Za-z0-9_]{0,63}$"
      },
      "description": "Field names to return (case-sensitive, from method_get_table_fields). Without a select Method returns hundreds of columns per row."
    },
    "top": {
      "description": "Rows per page, 1-100 (default 25).",
      "type": "integer",
      "exclusiveMinimum": 0,
      "maximum": 100
    },
    "skip": {
      "description": "Rows to skip (default 0). Pass the previous reply's next_skip.",
      "type": "integer",
      "minimum": 0,
      "maximum": 10000000
    }
  },
  "$schema": "https://json-schema.org/draft/2020-12/schema"
}
🟢method_list_invoices(customer_id, unpaid_only, created_since, select, top, ...)

List invoices, newest first, optionally only unpaid ones (BalanceRemaining > 0), one customer's (customer_id = Customer RecordID) or created since a time. Returns reference number, customer, dates, amount and balance; override `select` for other fields. For totals use method_query_records with `apply`. GET /api/v1/tables/Invoice.

输入模式

{
  "type": "object",
  "properties": {
    "customer_id": {
      "description": "Only invoices of this customer (Customer RecordID).",
      "type": "integer",
      "exclusiveMinimum": 0,
      "maximum": 2147483647
    },
    "unpaid_only": {
      "description": "Only invoices with an outstanding balance.",
      "type": "boolean"
    },
    "created_since": {
      "type": "string",
      "description": "ISO 8601 date-time WITH a timezone (Z or +hh:mm), e.g. 2026-10-01T00:00:00Z."
    },
    "select": {
      "minItems": 1,
      "maxItems": 60,
      "type": "array",
      "items": {
        "type": "string",
        "pattern": "^[A-Za-z][A-Za-z0-9_]{0,63}$"
      },
      "description": "Field names to return (case-sensitive, from method_get_table_fields). Without a select Method returns hundreds of columns per row."
    },
    "top": {
      "description": "Rows per page, 1-100 (default 25).",
      "type": "integer",
      "exclusiveMinimum": 0,
      "maximum": 100
    },
    "skip": {
      "description": "Rows to skip (default 0). Pass the previous reply's next_skip.",
      "type": "integer",
      "minimum": 0,
      "maximum": 10000000
    }
  },
  "$schema": "https://json-schema.org/draft/2020-12/schema"
}
🟢method_list_files(table, record_id)

List the files attached to a record (name, size, who added it, id). Use the id with method_get_file_url. GET /api/v1/files.

输入模式

{
  "type": "object",
  "properties": {
    "table": {
      "type": "string",
      "pattern": "^[A-Za-z][A-Za-z0-9_]{0,63}$",
      "description": "Table name exactly as method_list_tables shows it, e.g. Customer, Contacts, Activity, Invoice, Estimate."
    },
    "record_id": {
      "type": "integer",
      "exclusiveMinimum": 0,
      "maximum": 2147483647,
      "description": "The record's RecordID."
    }
  },
  "required": [
    "table",
    "record_id"
  ],
  "$schema": "https://json-schema.org/draft/2020-12/schema"
}
🟢method_get_file_url(file_id)

A temporary download link (valid 20 minutes) for an attached file, by the file id from method_list_files. The link works without the API key: share it only with someone allowed to see the file. GET /api/v1/files/{id}/url.

输入模式

{
  "type": "object",
  "properties": {
    "file_id": {
      "type": "string",
      "pattern": "^[A-Za-z0-9-]{8,64}$",
      "description": "File id (a GUID)."
    }
  },
  "required": [
    "file_id"
  ],
  "$schema": "https://json-schema.org/draft/2020-12/schema"
}
🔴method_create_customer(name, is_lead, first_name, last_name, email, ...)

WRITE: creates a record in Method's Customer table. is_lead true = a Customer Lead (does not sync to the accounting system); is_lead false = a full customer, which Method syncs to QuickBooks/Xero (it appears there too). Method also creates the primary Contact; its RecordID is returned as contact_id when it could be found (use it, not the customer id, to link activities). Name is required (for a person with no company use "First Last"). `extra_fields` sets other fields by their exact names (see method_get_table_fields, table Customer). Not idempotent: calling twice creates two records, so search first (method_search_customers). POST /api/v1/tables/Customer.

输入模式

{
  "type": "object",
  "properties": {
    "name": {
      "type": "string",
      "minLength": 1,
      "maxLength": 200,
      "description": "Display name of the customer or lead."
    },
    "is_lead": {
      "type": "boolean",
      "description": "true = lead (not synced to accounting), false = customer (synced to QuickBooks/Xero)."
    },
    "first_name": {
      "type": "string",
      "maxLength": 100
    },
    "last_name": {
      "type": "string",
      "maxLength": 100
    },
    "email": {
      "type": "string",
      "maxLength": 254
    },
    "phone": {
      "type": "string",
      "maxLength": 50
    },
    "lead_status": {
      "description": "Account-defined lead status, e.g. Open (leads only).",
      "type": "string",
      "maxLength": 100
    },
    "assigned_to_id": {
      "description": "Owner: a Method user id (method_get_account, or the Users table).",
      "type": "integer",
      "exclusiveMinimum": 0,
      "maximum": 2147483647
    },
    "extra_fields": {
      "type": "object",
      "propertyNames": {
        "type": "string",
        "pattern": "^[A-Za-z][A-Za-z0-9_]{0,63}$"
      },
      "additionalProperties": {
        "anyOf": [
          {
            "type": "string",
            "maxLength": 8000
          },
          {
            "type": "number"
          },
          {
            "type": "boolean"
          },
          {
            "type": "null"
          }
        ]
      },
      "description": "Field name -> value, exactly as method_get_table_fields names them (case-sensitive; a misspelled name is silently ignored by Method). For a dropdown/linked field send the integer id in its `_RecordID` field (e.g. Customer_RecordID: 1234), not the caption."
    }
  },
  "required": [
    "name",
    "is_lead"
  ],
  "$schema": "https://json-schema.org/draft/2020-12/schema"
}
🔴method_create_activity(entity_id, comments, activity_type_id, activity_type, contact_id, ...)

WRITE: logs an activity (call, email, to-do, note) on a customer/lead. entity_id is the Customer RecordID; contact_id is the Contact RecordID (not the Customer's; method_list_contacts finds it). The text goes in Comments. Prefer activity_type_id (read it from an existing activity of that type) over the caption activity_type: a caption that matches zero or several options is silently dropped. Method requires an assignee on standard accounts. The reply re-reads the activity so you can check the links were stored (field names are account-specific; method_get_table_fields with table Activity shows them). It does not email anyone. Not idempotent. POST /api/v1/tables/Activity.

输入模式

{
  "type": "object",
  "properties": {
    "entity_id": {
      "type": "integer",
      "exclusiveMinimum": 0,
      "maximum": 2147483647,
      "description": "The Customer (entity) RecordID the activity belongs to, so it shows in its history."
    },
    "comments": {
      "type": "string",
      "minLength": 1,
      "maxLength": 8000,
      "description": "The note body."
    },
    "activity_type_id": {
      "description": "ActivityType_RecordID from an existing activity of the wanted type.",
      "type": "integer",
      "exclusiveMinimum": 0,
      "maximum": 2147483647
    },
    "activity_type": {
      "description": "Activity type caption, e.g. Call. Use only if you have no id.",
      "type": "string",
      "minLength": 1,
      "maxLength": 100
    },
    "contact_id": {
      "description": "The Contact RecordID.",
      "type": "integer",
      "exclusiveMinimum": 0,
      "maximum": 2147483647
    },
    "assigned_to_id": {
      "description": "Method user id of the owner (method_get_account).",
      "type": "integer",
      "exclusiveMinimum": 0,
      "maximum": 2147483647
    },
    "status_id": {
      "description": "ActivityStatus_RecordID (account-defined, e.g. Not Started / Completed).",
      "type": "integer",
      "exclusiveMinimum": 0,
      "maximum": 2147483647
    },
    "due": {
      "description": "Due/start time, YYYY-MM-DDTHH:mm:ss.",
      "type": "string"
    }
  },
  "required": [
    "entity_id",
    "comments"
  ],
  "$schema": "https://json-schema.org/draft/2020-12/schema"
}
🔴method_create_record(table, fields)

WRITE: creates a record in any table that allows it (method_list_tables shows canCreate), e.g. Estimate, Invoice, Item, Vendor. For customers/leads and activities use the dedicated tools. Field names are case-sensitive and a wrong one is silently ignored: read them with method_get_table_fields first, and send dropdown links as their `_RecordID` integer. Creating accounting records (Invoice, Estimate, Customer ...) makes Method sync them to QuickBooks/Xero. Child lines (InvoiceLine ...) are not supported here. Not idempotent. Returns the new RecordID. POST /api/v1/tables/{table}.

输入模式

{
  "type": "object",
  "properties": {
    "table": {
      "type": "string",
      "pattern": "^[A-Za-z][A-Za-z0-9_]{0,63}$",
      "description": "Table name exactly as method_list_tables shows it, e.g. Customer, Contacts, Activity, Invoice, Estimate."
    },
    "fields": {
      "type": "object",
      "propertyNames": {
        "type": "string",
        "pattern": "^[A-Za-z][A-Za-z0-9_]{0,63}$"
      },
      "additionalProperties": {
        "anyOf": [
          {
            "type": "string",
            "maxLength": 8000
          },
          {
            "type": "number"
          },
          {
            "type": "boolean"
          },
          {
            "type": "null"
          }
        ]
      },
      "description": "Field name -> value, exactly as method_get_table_fields names them (case-sensitive; a misspelled name is silently ignored by Method). For a dropdown/linked field send the integer id in its `_RecordID` field (e.g. Customer_RecordID: 1234), not the caption."
    }
  },
  "required": [
    "table",
    "fields"
  ],
  "$schema": "https://json-schema.org/draft/2020-12/schema"
}
🔴method_update_record(table, record_id, fields)

WRITE: changes fields on one record (PATCH: only the fields you pass change). Field names are case-sensitive and Method silently ignores wrong or read-only names, so the reply re-reads the record and shows the stored values of the fields you sent: check them. Linked fields are changed through their `_RecordID` integer field. Updating accounting records (Customer, Invoice ...) makes Method sync the change to QuickBooks/Xero; setting IsLeadStatusOnly to false converts a lead into a synced customer. There is no delete tool. PATCH /api/v1/tables/{table}/{recordId}.

输入模式

{
  "type": "object",
  "properties": {
    "table": {
      "type": "string",
      "pattern": "^[A-Za-z][A-Za-z0-9_]{0,63}$",
      "description": "Table name exactly as method_list_tables shows it, e.g. Customer, Contacts, Activity, Invoice, Estimate."
    },
    "record_id": {
      "type": "integer",
      "exclusiveMinimum": 0,
      "maximum": 2147483647,
      "description": "The record's RecordID."
    },
    "fields": {
      "type": "object",
      "propertyNames": {
        "type": "string",
        "pattern": "^[A-Za-z][A-Za-z0-9_]{0,63}$"
      },
      "additionalProperties": {
        "anyOf": [
          {
            "type": "string",
            "maxLength": 8000
          },
          {
            "type": "number"
          },
          {
            "type": "boolean"
          },
          {
            "type": "null"
          }
        ]
      },
      "description": "Field name -> value, exactly as method_get_table_fields names them (case-sensitive; a misspelled name is silently ignored by Method). For a dropdown/linked field send the integer id in its `_RecordID` field (e.g. Customer_RecordID: 1234), not the caption."
    }
  },
  "required": [
    "table",
    "record_id",
    "fields"
  ],
  "$schema": "https://json-schema.org/draft/2020-12/schema"
}

社区

评价此服务器

证据

最近观测

已验证未记录版本16 个工具