Skip to content

Add twchat toolset for Teamwork Chat#347

Open
4ver wants to merge 3 commits into
mainfrom
add-twchat-toolset
Open

Add twchat toolset for Teamwork Chat#347
4ver wants to merge 3 commits into
mainfrom
add-twchat-toolset

Conversation

@4ver
Copy link
Copy Markdown
Member

@4ver 4ver commented Jun 2, 2026

Summary

Adds a new twchat toolset exposing basic Teamwork Chat support, alongside the existing twprojects, twspaces, and twdesk toolsets.

The Chat API is served at /chat/v7/... on the same installation host as the Projects API and authenticates with the same bearer token, so these tools ride the existing twapi.Engine via custom HTTPRequester types and stream the raw JSON response through twapi.ExecuteRaw. No new SDK dependency or config is required.

Tools

Six tools under one sub-toolset (twchat-chat) — 5 read + 1 write (send_message is gated automatically by read-only mode):

Tool Endpoint
twchat-get_current_user GET /chat/v7/me
twchat-list_conversations GET /chat/v7/conversations
twchat-get_conversation GET /chat/v7/conversations/:id
twchat-list_messages GET /chat/v7/conversations/:id/messages
twchat-list_people GET /chat/v7/people
twchat-send_message POST /chat/v7/conversations/:id/messages

Implementation

  • New package internal/twchat/: tools.go (registration + DefaultToolsetGroup), requests.go (the HTTPRequester types), chat.go (tool constructors + shared execute helper).
  • Registered the group in cmd/mcp-stdio/main.go and cmd/mcp-http/main.go.
  • Added testutil.ChatMCPServerMock (reuses the existing ProjectsEngineMock) plus one test per tool.
  • Output is raw JSON passthrough (no typed structs / output schemas), matching the twprojects budget/list pattern.

Verification

gofmt -s, go build ./..., go vet ./..., and go test ./... all pass; the new twchat tests are green.

Out of scope (future)

Reactions, starring, conversation create/update/leave, attachments/file upload, and message edit/delete — easy follow-ups on the same pattern.

Wrap six Teamwork Chat API endpoints as MCP tools: get_current_user,
list_conversations, get_conversation, list_messages, list_people (reads)
and send_message (write, gated by read-only mode).

The Chat API is served at /chat/v7/... on the same installation host as
the Projects API and uses the same bearer token, so the tools ride the
existing twapi.Engine via custom HTTPRequester types and stream the raw
JSON response through twapi.ExecuteRaw. No new SDK or config required.

Register the group in the stdio and http entry points and add a
ChatMCPServerMock test helper reusing ProjectsEngineMock.
@4ver 4ver requested a review from a team as a code owner June 2, 2026 12:52
Add get_or_create_dm (GET /chat/v7/people/:id/conversation) to resolve or
create the 1:1 pair conversation with a person, and send_dm, a convenience
write tool that resolves that conversation and posts a message in one call.
There is no server-side "send to person" endpoint, so send_dm composes the
two calls client-side.

Also expose filter[type] (rooms|pair) on list_conversations so agents can
narrow to direct messages or group conversations.
Comment thread internal/twchat/chat.go Outdated
Comment thread internal/twchat/chat.go Outdated
Comment thread cmd/mcp-http/main.go
@rafaeljusto
Copy link
Copy Markdown
Contributor

There's also some tool filtering depending on what scope your token allows here:

projectsScope := slices.Contains(scopes, "projects")
deskScope := slices.Contains(scopes, "desk")
spacesScope := slices.Contains(scopes, "spaces")
listToolsResult.Tools = slices.DeleteFunc(listToolsResult.Tools, func(tool *mcp.Tool) bool {
return (strings.HasPrefix(tool.Name, "twprojects") && !projectsScope) ||
(strings.HasPrefix(tool.Name, "twdesk") && !deskScope) ||
(strings.HasPrefix(tool.Name, "twspaces") && !spacesScope)
})

@tw-garymeehan
Copy link
Copy Markdown
Contributor

tw-garymeehan commented Jun 2, 2026

All non-blocking.

Reviewed by Claude against some token optimisation work we've done recently 🤖

Token-count review (scoped to tool/param descriptions) — summary to go with the two inline notes above.

Verdict: lean and on-convention — not a bloat problem. Measured with cmd/mcp-tokens (tiktoken o200k_base): the 8 twchat tools add 1,049 tokens / ~2.6% to the registry, and the list tools are actually cheaper than comparable helper-based ones (list_messages 295 / list_conversations 266 vs twprojects-list_comments 405).

Two things worth addressing:

  1. cmd/mcp-tokens isn't updated to include twchat. allGroups() (cmd/mcp-tokens/main.go:108-112) lists only twprojects + twdesk + twspaces, so the token-budget tracker from Add mcp-tokens command to measure tool token costs #300 is blind to these ~1,049 tokens and every future -base=main delta silently omits them. Fix is one line: add twchat.DefaultToolsetGroup(false, nil) to allGroups() (plus the import).

  2. Shared schema helpers aren't reused — see the two inline comments on internal/twchat/chat.go (search-term / pagination / date-time filters already exist in internal/helpers/schema.go from Refactor: Add shared schema helpers for pagination, tag, and search params #306).

- Reuse helpers.SearchTermSchema/PageSchema/PageOffsetSchema and
  DateTimeFilterSchema in the twchat tools for consistency with the other
  toolsets; keep page_limit/page_size inline since they carry the API's
  max-10 / 1-200 ranges.
- Add "chat" to scopes_supported in the OAuth protected-resource metadata.
- Gate twchat tools behind the "chat" scope in the tool-list filter, mirroring
  the projects/desk/spaces handling.
@4ver
Copy link
Copy Markdown
Member Author

4ver commented Jun 2, 2026

Still have to test. Okay to chuck it onto staging to give it a go?

@rafaeljusto
Copy link
Copy Markdown
Contributor

Still have to test. Okay to chuck it onto staging to give it a go?

Fire away. Changes should trigger a build once merged to the staging branch.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants