Skip to content

Conversation

@rafaeljusto
Copy link
Contributor

Adds the official Teamwork.com MCP server to the registry: https://github.com/Teamwork/mcp

The MCP server (HTTP) is available at:
https://mcp.ai.teamwork.com

Additional information can be found at:
https://www.teamwork.com/product/ai/

MCP Server Information

Server Name: Teamwork.com
Repository URL: https://github.com/Teamwork/mcp
Brief Description: Provides a standardised interface for LLMs to interact with Teamwork.com, allowing AI agents to perform various project management operations.

Basic Requirements

  • Open Source: Uses acceptable license (Apache-2.0, MIT, BSD-2-Clause, BSD-3-Clause or other permissive license)
  • MCP Compliant: Implements MCP API specification
  • Active Development: Recent commits and maintained
  • Docker Artifact: Dockerfile
  • Documentation: Basic README and setup instructions
  • Security Contact: Method for reporting security issues

Submitter Checklist

  • This server meets the basic requirements listed above
  • I understand this will undergo automated and manual review.
  • I have tested the MCP Server using task validate -- --name SERVER_NAME
  • I have built the MCP Server using task build -- --tools SERVER_NAME

Adds the official Teamwork.com MCP server to the registry:
https://github.com/Teamwork/mcp

The MCP server is available at:
https://mcp.ai.teamwork.com

Additional information can be found at:
https://www.teamwork.com/product/ai/
@rafaeljusto rafaeljusto requested a review from a team as a code owner August 15, 2025 19:14
@ipedrazas
Copy link
Contributor

When I run task build -- --tools teamwork, the docker build succeeds, but the listing of tools fails:

2025/08/21 11:34:05 initializing mcp/teamwork:
exit status 1
task: Failed to run task "build": exit status 1

This is usually because you need to have a valid connection to the 3rd party system before listing tools. The easiest way to fix this is to make the listing tools independent of the initialisation.

@rafaeljusto
Copy link
Contributor Author

Could we allow authenticated tool listing by injecting environment variables?

The following patch would work:

diff --git a/cmd/build/main.go b/cmd/build/main.go
index 1e622f1..160135c 100644
--- a/cmd/build/main.go
+++ b/cmd/build/main.go
@@ -58,6 +58,13 @@ func run(ctx context.Context, name string, listTools bool, pullCommunity bool) e
        }
 
        if listTools {
+               for i, secret := range server.Config.Secrets {
+                       if env, ok := os.LookupEnv(secret.Env); ok {
+                               secret.Example = env
+                               server.Config.Secrets[i] = secret
+                       }
+               }
+
                tools, err := mcp.Tools(ctx, server, false, false, false)
                if err != nil {
                        return err

Example:

$ TW_MCP_BEARER_TOKEN=tkn.v1_... go run cmd/build/main.go --tools teamwork
[+] Building 2.8s (18/18) FINISHED                                                                                             docker-container:silly_euler
 => CACHED [internal] load git source https://github.com/teamwork/mcp.git#main                                                                         0.9s
 => resolve image config for docker-image://docker.io/docker/dockerfile:1                                                                              0.7s
 => CACHED docker-image://docker.io/docker/dockerfile:1@sha256:38387523653efa0039f8e1c89bb74a30504e76ee9f565e25c9a09841f9427b05                        0.0s
 => => resolve docker.io/docker/dockerfile:1@sha256:38387523653efa0039f8e1c89bb74a30504e76ee9f565e25c9a09841f9427b05                                   0.0s
 => [internal] load metadata for docker.io/library/golang:1.24-alpine                                                                                  0.4s
 => [internal] load metadata for docker.io/library/alpine:3                                                                                            0.2s
 => [builder 1/6] FROM docker.io/library/golang:1.24-alpine@sha256:c8c5f95d64aa79b6547f3b626eb84b16a7ce18a139e3e9ca19a8c078b85ba80d                    0.0s
 => => resolve docker.io/library/golang:1.24-alpine@sha256:c8c5f95d64aa79b6547f3b626eb84b16a7ce18a139e3e9ca19a8c078b85ba80d                            0.0s
 => [runner 1/5] FROM docker.io/library/alpine:3@sha256:4bcff63911fcb4448bd4fdacec207030997caf25e9bea4045fa6c8c44de311d1                               0.0s
 => => resolve docker.io/library/alpine:3@sha256:4bcff63911fcb4448bd4fdacec207030997caf25e9bea4045fa6c8c44de311d1                                      0.0s
 => CACHED [builder 2/6] WORKDIR /usr/src/mcp                                                                                                          0.0s
 => CACHED [builder 3/6] COPY --chown=root:root . /usr/src/mcp                                                                                         0.0s
 => CACHED [builder 4/6] RUN go mod download                                                                                                           0.0s
 => CACHED [builder 5/6] RUN go build -ldflags="-X 'github.com/teamwork/mcp/internal/config.Version=dev'" -o /app/tw-mcp-http ./cmd/mcp-http           0.0s
 => CACHED [builder 6/6] RUN go build -ldflags="-X 'github.com/teamwork/mcp/internal/config.Version=dev'" -o /app/tw-mcp-stdio ./cmd/mcp-stdio         0.0s
 => CACHED [runner 2/5] COPY --from=builder /app/tw-mcp-http /bin/tw-mcp-http                                                                          0.0s
 => CACHED [runner 3/5] COPY --from=builder /app/tw-mcp-stdio /bin/tw-mcp-stdio                                                                        0.0s
 => CACHED [runner 4/5] RUN addgroup -S mcp && adduser -S mcp -G mcp                                                                                   0.0s
 => CACHED [runner 5/5] RUN chown mcp:mcp /bin/tw-mcp-http /bin/tw-mcp-stdio && chmod 0755 /bin/tw-mcp-http /bin/tw-mcp-stdio                          0.0s
 => exporting to docker image format                                                                                                                   0.6s
 => => exporting layers                                                                                                                                0.0s
 => => exporting manifest sha256:1228337f403de09c2ac5dbaf8e529fa81d639a38e1b325c24d28df95784e48d2                                                      0.0s
 => => exporting config sha256:3544a635b4e1cc9cea4456ab16e99b9c5d15ff9fa1eaa3f172bb9c425e412252                                                        0.0s
 => => sending tarball                                                                                                                                 0.6s
 => importing to docker                                                                                                                                0.0s

55 tools found.

-----------------------------------------

✅ Image built as mcp/teamwork

It appears to be a good practice to expose tools/resources/prompts/roots only after authentication. That said, it's not enforced by the protocol documentation. Is it a requirement for the Docker MCP registry?

@ipedrazas
Copy link
Contributor

It appears to be a good practice to expose tools/resources/prompts/roots only after authentication.

Really? In my experience, people often struggle to configure MCP servers properly. Expecting valid auth to expose tools/... makes things even harder because you cannot add helper tools/prompts to onboard users.

You could write a tool/prompt that helps the user (via agent) to configure the MCP properly. For example, where does the user generates that token/secret?

Regarding this option: TW_MCP_BEARER_TOKEN=tkn.v1_... go run cmd/build/main.go --tools teamwork

Yes, we could do that, but who's providing that token value? when we build the docker images, we list the tools. This means that we should add all those secrets and variables to the build process, which is not ideal.

We need 2 assets to display the MCP correctly: a readme and a tools definition file. I guess that we could ask the user to provide them if their MCP exposes tools after auth.

I'm very open to change the process to make it as easy/smooth as possible, so, any suggestions are welcome :)

rafaeljusto added a commit to Teamwork/mcp that referenced this pull request Aug 22, 2025
This is a requirement for the Docker MCP registry.

Related to:
docker/mcp-registry#164
rafaeljusto added a commit to Teamwork/mcp that referenced this pull request Aug 22, 2025
This is a requirement for the Docker MCP registry.

Related to:
docker/mcp-registry#164
rafaeljusto added a commit to Teamwork/mcp that referenced this pull request Aug 22, 2025
This is a requirement for the Docker MCP registry.

Related to:
docker/mcp-registry#164
@rafaeljusto
Copy link
Contributor Author

Hey @ipedrazas, thanks for the quick reply! I didn’t have a strong preference regarding authenticated methods, just wanted to be extra cautious about security 😄 It makes sense for tool listings to be unauthenticated since the Docker MCP registry will display them. 👍 I’ve updated the MCP server so tools can now be listed without authentication, and the build CLI seems to be working as expected:

$ go run cmd/build/main.go --tools teamwork
[+] Building 50.8s (18/18) FINISHED                                                                                            docker-container:silly_euler
 => [internal] load git source https://github.com/teamwork/mcp.git#main                                                                                2.0s
 => resolve image config for docker-image://docker.io/docker/dockerfile:1                                                                              1.3s
 => CACHED docker-image://docker.io/docker/dockerfile:1@sha256:38387523653efa0039f8e1c89bb74a30504e76ee9f565e25c9a09841f9427b05                        0.0s 
 => => resolve docker.io/docker/dockerfile:1@sha256:38387523653efa0039f8e1c89bb74a30504e76ee9f565e25c9a09841f9427b05                                   0.0s 
 => [internal] load metadata for docker.io/library/golang:1.24-alpine                                                                                  0.4s
 => [internal] load metadata for docker.io/library/alpine:3                                                                                            0.6s
 => [builder 1/6] FROM docker.io/library/golang:1.24-alpine@sha256:c8c5f95d64aa79b6547f3b626eb84b16a7ce18a139e3e9ca19a8c078b85ba80d                    0.0s
 => => resolve docker.io/library/golang:1.24-alpine@sha256:c8c5f95d64aa79b6547f3b626eb84b16a7ce18a139e3e9ca19a8c078b85ba80d                            0.0s
 => [runner 1/5] FROM docker.io/library/alpine:3@sha256:4bcff63911fcb4448bd4fdacec207030997caf25e9bea4045fa6c8c44de311d1                               0.0s
 => => resolve docker.io/library/alpine:3@sha256:4bcff63911fcb4448bd4fdacec207030997caf25e9bea4045fa6c8c44de311d1                                      0.0s
 => CACHED [builder 2/6] WORKDIR /usr/src/mcp                                                                                                          0.0s
 => [builder 3/6] COPY --chown=root:root . /usr/src/mcp                                                                                                0.0s
 => [builder 4/6] RUN go mod download                                                                                                                 26.8s
 => [builder 5/6] RUN go build -ldflags="-X 'github.com/teamwork/mcp/internal/config.Version=dev'" -o /app/tw-mcp-http ./cmd/mcp-http                 16.0s
 => [builder 6/6] RUN go build -ldflags="-X 'github.com/teamwork/mcp/internal/config.Version=dev'" -o /app/tw-mcp-stdio ./cmd/mcp-stdio                1.0s
 => CACHED [runner 2/5] COPY --from=builder /app/tw-mcp-http /bin/tw-mcp-http                                                                          0.0s
 => [runner 3/5] COPY --from=builder /app/tw-mcp-stdio /bin/tw-mcp-stdio                                                                               0.0s
 => [runner 4/5] RUN addgroup -S mcp && adduser -S mcp -G mcp                                                                                          0.1s
 => [runner 5/5] RUN chown mcp:mcp /bin/tw-mcp-http /bin/tw-mcp-stdio && chmod 0755 /bin/tw-mcp-http /bin/tw-mcp-stdio                                 0.2s
 => exporting to docker image format                                                                                                                   2.6s
 => => exporting layers                                                                                                                                1.6s
 => => exporting manifest sha256:6a0508093b68cd92f7730c4b7721b575685e76ed6e26d3f05d0637cb7b3eb644                                                      0.0s
 => => exporting config sha256:9666e1796968fdeac1b3f211bc09d9b8bfebaa641677c759599a51d7464f4483                                                        0.0s
 => => sending tarball                                                                                                                                 1.0s
 => importing to docker                                                                                                                                0.4s
 => => loading layer ce779117af2c 16.57MB / 16.57MB                                                                                                    0.4s
 => => loading layer ee6f916e8b67 945B / 945B                                                                                                          0.3s
 => => loading layer 96f5083ccab9 33.61MB / 33.61MB                                                                                                    0.3s
time=2025-08-22T18:20:58.659Z level=ERROR msg="failed to get bearer info" error="unauthorized: failed to get bearer info"

62 tools found.

-----------------------------------------

✅ Image built as mcp/teamwork

Please let me know if you need anything else.

@rafaeljusto
Copy link
Contributor Author

Hi @ipedrazas, whenever you get a chance, could you take another look at this PR? I believe everything should be in order now, but let me know if you spot anything else.

@ipedrazas
Copy link
Contributor

This is great, thanks!

@ipedrazas ipedrazas merged commit a512280 into docker:main Sep 2, 2025
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants