
I confirmed the range that AI can and cannot handle by operating from Claude Code with the official Perforce MCP.
This page has been translated by machine translation. View original
Introduction
Git has become naturally usable from AI agents like Claude Code. It can help explain diffs, generate commit messages, and resolve conflicts. On the other hand, you don't hear much about similar AI integration for Perforce, which is used in game development and elsewhere.
In this article, I connect Perforce's officially provided MCP server p4mcp-server to Claude Code, and actually distinguish what AI can and cannot handle for both read and write operations. To state the conclusion upfront: text-related tasks such as querying change history and creating changelist descriptions worked well with AI, while binary file contents could not be handled by AI.
This article also includes the steps from setup to connection so you can reproduce it on your own machine.
What is Perforce?
Perforce is a centralized version control system widely used in development environments that handle large binary files with many contributors. It is frequently adopted in game development, and its key features are exclusive file locking where one person edits a file at a time, and partial sync that retrieves only the files you need. The server process is called p4d, and the client is called p4.
Verification Environment
- macOS
- Helix Core p4d 2025.2
- p4mcp-server 3.3.1
- Claude Code
- uv and Python 3.14
Target Audience
- Those who operate Perforce and want to know how far AI can be utilized
- Those who handle large binary assets and find tracking change history and reviews cumbersome
- Those who want to connect an MCP server to actual business tools
References
- P4 MCP Product Page (Perforce Official)
- P4 MCP Server Documentation (Perforce Official)
- perforce/p4mcp-server (GitHub)
- Model Context Protocol
Background and Problem Statement
In Perforce operations, you manage things like who introduced a particular change, what a changelist was intended for, how a file has changed recently, and how newcomers trace past history. With Git, you can simply ask Claude Code, but whether Perforce had the same capability had not been clearly established until now.
There is a structural reason behind this. The core of Perforce is managing large binaries that cannot be merged. In this domain, large language models (LLMs) cannot read the contents, making it hard to see the benefits of AI. This contrasts with Git, where text diffs—the core of Git—overlap with what LLMs do well.
However, upon investigation, Perforce was officially providing an MCP server. The first release in the official repository was in September 2025, and it is positioned as community supported. This article distinguishes what this MCP actually solves and what it does not. I verify through testing the answers to questions like whether text-related research such as change history and reviews can be delegated to AI, and whether managing binary assets themselves becomes easier with AI.
Verification Method
I set up Perforce locally, create a change history that includes both text and binaries, then connect the official p4mcp-server to Claude Code. I first test read-only queries, then write operations.
Starting p4d
Perforce's p4d and p4 can be obtained from the official download page.
mkdir -p p4root
p4d -r "$PWD/p4root" -p 1666 -L "$PWD/p4d.log" -J "$PWD/p4root/journal" -d
# Disable authentication for verification. Do not use in production
p4 -p 1666 configure set security=0
Creating Change History with Two Users
To make queries meaningful, I create history with two users, tester_a and tester_b, including text, exclusively locked binaries, and non-exclusively locked binaries.
2-sample-history.sh
export P4PORT=1666
# Create workspace for tester_a
P4USER=tester_a P4CLIENT=ws_a p4 client -i <<EOF
Client: ws_a
Owner: tester_a
Root: $PWD/ws_a
View:
//depot/... //ws_a/...
EOF
mkdir -p ws_a && cd ws_a
# CL1: Text and exclusively locked binary
printf 'baseline notes\n' > notes.txt
head -c 1048576 /dev/urandom > assetX.bin
p4 -u tester_a -c ws_a add -t text notes.txt
p4 -u tester_a -c ws_a add -t binary+l assetX.bin
p4 -u tester_a -c ws_a submit -d "baseline: notes.txt and assetX.bin"
# CL2: Add non-exclusively locked binary
head -c 524288 /dev/urandom > assetW.bin
p4 -u tester_a -c ws_a add -t binary+w assetW.bin
p4 -u tester_a -c ws_a submit -d "add assetW.bin (binary+w)"
# CL3: tester_a edits assetW
p4 -u tester_a -c ws_a edit assetW.bin
head -c 524288 /dev/urandom > assetW.bin
p4 -u tester_a -c ws_a submit -d "A edits assetW"
cd ..
# Create workspace for tester_b and edit assetW (CL4)
P4USER=tester_b P4CLIENT=ws_b p4 client -i <<EOF
Client: ws_b
Owner: tester_b
Root: $PWD/ws_b
View:
//depot/... //ws_b/...
EOF
mkdir -p ws_b && cd ws_b
p4 -u tester_b -c ws_b sync
p4 -u tester_b -c ws_b edit assetW.bin
head -c 524288 /dev/urandom > assetW.bin
p4 -u tester_b -c ws_b submit -d "B edits assetW"
cd ..
Connecting the Official MCP Server to Claude Code
p4mcp-server can be obtained via uvx. Since this article tests both read and write operations, I connect two instances under different names: one read-only and one with write access.
# For queries: read-only. Write tools are not exposed
claude mcp add p4lab \
--env P4PORT=localhost:1666 --env P4USER=tester_a --env P4CLIENT=ws_a \
-- uvx p4mcp-server --readonly
# For writes: without --readonly
claude mcp add p4lab-rw \
--env P4PORT=localhost:1666 --env P4USER=tester_a --env P4CLIENT=ws_a \
-- uvx p4mcp-server
After connecting, confirm that both show as connected in Claude Code's /mcp. With read-only p4lab, only 8 query tools are exposed, and write tools do not appear. I use p4lab-rw for write verification.
Verification Results
Queries (Read-Only)
First, when I asked for information about the connected server, it returned the server version, address, and authenticated user in a table.
[Prompt]
Tell me about the connected Perforce server
[Response (excerpt)]
Here is the information about the connected Perforce server.
## Server
| Item | Value |
|---|---|
| Server Address | `localhost:1666` |
| Server Version | P4D/MACOSX12ARM64/2025.2/2907753 (2026/03/09) |
| Service Type | standard |
| License | none (not set) |
## Authenticated User
| Item | Value |
|---|---|
| User | `tester_a` |
| Type | standard |
| Authentication Method | perforce |
This is a verification P4D server running locally (`localhost:1666`).
Next, I asked it to list changelists in reverse chronological order and summarize them. It compiled who changed what into a table and bullet points, and even read the file type differences.
[Prompt]
List changelists in reverse chronological order and summarize who changed what
[Response (supplementary notes omitted)]
Here are the changelists listed in reverse chronological order. All 6 are submitted to `//depot`, with 2 users: `tester_a` and `tester_b`.
## Changelists in Reverse Chronological Order
| CL | Date/Time (JST) | User | Summary |
|---|---|---|---|
| 6 | 07/18 20:30 | tester_a | Created branch in branch1 (lazy copy) |
| 5 | 07/18 20:08 | tester_a | Added model.uasset |
| 4 | 07/18 20:05 | tester_b | Edited assetW.bin |
| 3 | 07/18 20:05 | tester_a | Edited assetW.bin |
| 2 | 07/18 20:04 | tester_a | Added assetW.bin |
| 1 | 07/18 20:02 | tester_a | Created baseline |
## Who Changed What (Details)
- CL4 — tester_b "B edits assetW" edited assetW.bin (rev.3). Type is binary+w (non-exclusive). Following tester_a's edit in CL3, a different user was able to update the same file.
- CL1 — tester_a "baseline: notes.txt (text), assetX/Y.bin (binary+l)" added notes.txt (text), assetX.bin and assetY.bin with exclusive lock (binary+l).
The output will vary depending on the depot's history, but this shows that understanding change history and reading file types can be delegated to natural language. Text file contents are also readable without issue. When I asked about notes.txt, it was displayed directly.
[Prompt]
Show me the contents of //depot/notes.txt
[Response]
Here are the contents of `//depot/notes.txt` (rev.1, text, 21 bytes).
```
baseline notes
line2
```
There have been no changes since it was added in CL1's baseline (still rev.1).
Up to this point, the experience is comparable to Git.
Binary files, however, behaved differently. When I asked for the contents of //depot/assetX.bin, Claude identified it as a 1 MB binary and judged that displaying it as-is would be meaningless. Rather than proceeding with a dump of the contents, it showed metadata such as type, size, and digest, and asked how I wanted to view it—offering options like change history, diff with another revision, or checking the actual local file. It stated on its own that dumping binary contents to the terminal consumes a large number of tokens and is not practical.
[Prompt]
Show me the contents of //depot/assetX.bin
[Response]
`//depot/assetX.bin` is a **binary file** (type: `binary+l`, size 1,048,576 bytes = 1MB). Since it is not text, displaying the raw contents would not produce meaningful information and would not fit in a terminal.
Here is the metadata:
| Item | Value |
|------|-----|
| head Rev | #2 (CL2) |
| Type | binary+l (binary with exclusive lock) |
| Size | 1,048,576 bytes (1MB) |
| digest | 05DE508D48FD6E6CB0D6236D77FC0BB4 |
This digest matches `//depot/branch1/assetX.bin` #1 branched in CL6, confirming that branch1 is a lazy copy of this content.
Note: Directly dumping binary+l binary contents to the terminal consumes a large number of tokens and is not practical, so I am avoiding displaying the raw content.
I also checked what would happen if I forced retrieval of the contents. Running the query tool's content directly on a binary caused the return value to balloon to 1,575,604 characters, exceeding the token limit and causing Claude Code to offload it to an external file rather than keeping it in context. Binary contents, even when forcibly passed to AI, do not become meaningful information.
Write Operations
First, I had AI write a changelist description and create a pending changelist. This is equivalent to the commit message generation use case with Git.
[Prompt]
Please create a pending changelist with the description "Update baseline notes in notes.txt"
[Response]
A pending changelist has been created.
| Item | Value |
|------|-----|
| Changelist | 9 |
| Status | pending |
| Description | Update baseline notes in notes.txt |
| User / Client | tester_a / ws_a |
No files have been added yet (empty pending).
The creation succeeded without issue. Since the description is text, write operations are also within AI's strengths.
Next, I tried opening a file for editing—the equivalent of p4 edit.
[Prompt]
Please open //depot/notes.txt for editing
[Response]
`//depot/notes.txt` has been opened for editing.
| Item | Value |
|------|-----|
| Changelist | 9 (pending) |
| Depot file | `//depot/notes.txt` |
| Target Revision | #1 → editing |
| Action | edit |
| Type | text+D |
The local notes.txt is now writable and has been placed in CL9.
The file was successfully opened for editing and placed in CL9, which was created earlier.
Next, I tried shelving this edit into a new changelist.
[Prompt]
Please put the open //depot/notes.txt into a new pending changelist and shelve it
[Response]
Done.
## Actions Taken
| Step | Result |
|---------|------|
| Created new pending changelist | CL10 (description: "Changelist to shelve notes.txt edits") |
| Moved file | Moved `//depot/notes.txt` from CL9 → CL10 |
| Shelved | Shelved `//depot/notes.txt` #1 (edit) in CL10 |
## Current State
- CL10 (pending): `//depot/notes.txt` is open for editing and shelved.
- CL9 (pending): File removed, now empty.
Creating a changelist, moving a file, and shelving were all accomplished with a single natural language instruction. These are all non-destructive operations, so they proceeded smoothly.
Next, as a destructive operation, I asked it to delete the created changelists. Claude cleaned up the shelved files and open files, then proceeded with deletion.
[Prompt]
Please delete the changelists you created
[Response (excerpt)]
I will delete both (CL9 and CL10). I will proceed in this order: delete CL10 shelve → revert file → delete changelist.
## Actions Taken
| Step | Result |
|---|---|
| Deleted CL10 shelve | Deleted shelve for `//depot/notes.txt` |
| Reverted file | Reverted `//depot/notes.txt` (no impact since unchanged) |
| Deleted CL10 | Change 10 deleted |
| Deleted CL9 | Change 9 deleted |
No open files or pending changelists remain. Returned to a clean state.
However, this deletion did not execute immediately. For destructive operations such as deleting shelves and changelists, the MCP server requests confirmation, and a dialog appears in Claude Code.
This is a confirmation for irreversible operations. The deletion is not executed unless you approve by selecting PROCEED.
Discussion
These results clearly illustrate the boundary of what AI can handle.
Binary contents, even when passed directly to AI, do not become meaningful information. It is nothing more than an endless stream of escaped characters byte by byte, and forcing retrieval can even exceed the token limit. That is precisely why a capable AI avoids dumping the contents and instead reasons through metadata and digests. In fact, Claude used the digest to verify that the original file and its branch contained identical content.
Text, on the other hand, was within AI's strengths for both reading and writing. Creating changelist descriptions can be delegated via natural language, and destructive operations like deletion include a confirmation step.
In other words, what MCP can handle is text-related work, such as understanding change history and summarizing or creating changelists. The reader concerns raised at the beginning fall within this scope. Managing large binaries themselves—the primary purpose of Perforce—is not something AI makes easier. The boundary between what can and cannot be handled maps directly onto Perforce's own boundary between text and binary.
Summary
Through its official MCP, Perforce can be operated from AI, and text-related tasks from querying change history to creating changelist descriptions can be delegated via natural language. Destructive operations like deletion include a confirmation step. Binary contents, however, cannot be passed to AI, and the scope of what can be handled is limited to text and metadata. I hope this article serves as useful reference material for deciding how to combine Perforce with AI.
