Skip to main content

walspro-ai

Headless OAuth device connector for wals.pro AI 4 weclapp.

Install it on an agent host that cannot receive a browser callback — a CLI agent, an SSH session, a container, a remote desktop. It performs an RFC 8628 device authorization against the hosted issuer and then forwards JSON-RPC frames between a local stdio MCP client and the hosted /v1/mcp runtime.

It is a transport and authentication adapter: it registers no MCP tools, implements no business logic, and never sees weclapp API credentials. Its optional local file transport supplies bytes to the server-owned preview/execute flow. The tool catalog, the user policy, the write-approval flow and the audit pipeline all stay on the server.

"weclapp" is the ERP this connector talks to. This distribution is published by Wals.pro GmbH and is not a weclapp SE product.


Before you start: wals.pro Support must enable device connections

Device authorization is off by default and is never derived from a plan or a tier. wals.pro Support enables it for each workspace.

Until then, the browser approval step explains that device connections are not enabled and asks you to contact wals.pro Support. The CLI reports expiration and timeouts as what they are; those outcomes alone do not prove a capacity problem.

Install

pipx install walspro-ai      # recommended: isolated, on PATH
pip install walspro-ai       # or into an existing environment

Python 3.10 or newer. The only runtime dependencies are the MCP SDK, httpx and anyio.

Use

walspro-ai login      # authorize this host (prints a URL and a user code)
walspro-ai status     # non-secret local connection status
walspro-ai config     # token-free MCP client configuration snippet
walspro-ai run        # stdio <-> /v1/mcp transport (started by the MCP client)
walspro-ai logout     # remove local credentials only
walspro-ai revoke     # revoke the server grant, then remove local credentials

python -m walspro_ai <command> is equivalent and works when the console script is not on PATH.

Add the output of walspro-ai config to your MCP client configuration. It contains no tokens; the credentials stay in the local credential file. Use --server-name to change the generated entry key.

Global options: --credentials PATH (alternate credential file), --verbose (print the underlying traceback on failure), --version.

login opens a browser only when one can plausibly be reached (a BROWSER variable, macOS/Windows, or DISPLAY/WAYLAND_DISPLAY). On a headless Linux host it prints the URL instead of blocking on a terminal browser. Force either behaviour with --open-browser or --no-browser.

Exit codes

Code Meaning
0 Success
1 Error (the message names the cause)
2 Local credentials were removed, but the server grant may still be active — revoke the connection in the dashboard
130 Interrupted (Ctrl-C)

Where credentials live

Platform Default path
Linux / BSD $XDG_CONFIG_HOME/walspro-ai/device.json, otherwise ~/.config/walspro-ai/device.json
macOS ~/.config/walspro-ai/device.json
Windows %APPDATA%\walspro-ai\device.json

The credential file is created exclusively (O_EXCL, O_NOFOLLOW) with mode 0600, rotated by fsync + atomic replace, and serialized across processes by an OS file lock on a sidecar. On POSIX the connector refuses to read a credential file that is group- or world-accessible or owned by another user.

Windows, stated plainly. Windows reports 0o666 for every writable file regardless of its ACL, so the mode assertion is skipped there, and there is no os.getuid() to compare against, so the ownership assertion is skipped too. This connector does not read the Windows ACL as a substitute. What remains on Windows is the symlink/regular-file check, the exclusive create and the atomic replace; the file's actual confidentiality is whatever the containing directory grants. Keep the credential file inside your own user profile (the default location does) and do not point --credentials at a shared directory. The POSIX checks themselves are never relaxed. Windows support is implemented and unit-tested (the platform branches are exercised directly) but continuous integration runs on Linux only, so please report anything that behaves differently there — support@wals.pro.

Ambient network configuration is trusted. Both HTTP stacks honour the process environment's proxy and CA settings (HTTPS_PROXY, SSL_CERT_FILE, and the platform trust store), which is what makes the connector work behind a corporate proxy. Treat the environment of the process your MCP client starts as part of the trust boundary, and review any env block you paste into a client configuration.

status and config never print bearer or refresh tokens.

Direct local file transfers

When an existing DeviceOAuth connection is already configured, enable local files on that same connector; no second login or browser handoff is needed:

walspro-ai config --file-root /absolute/path/to/upload-files
# The emitted client entry runs:
walspro-ai run --file-root /absolute/path/to/upload-files

The root belongs to the host running the connector. A path on another computer, a browser chat attachment, or a different container is not a local source for this process. Claude Code and Codex can invoke the connector through STDIO; they must see the updated local tool catalog. This setting does not enable local files for a remote-only Claude.ai or ChatGPT connection.

  1. Call create_upload_intent with its existing target fields and file_path, either relative to the configured root or an absolute path inside it. The local connector adds this argument to tools/list and removes it before forwarding the request. Use exactly one file source.
  2. The connector reads the file and calculates its size, MIME and SHA-256. It sends only metadata for the server's normal permission/target preview. No ERP upload occurs at this step. Review and approve the returned action.
  3. Call execute_approved with the returned token and unchanged execution payload. The connector sends the approved file bytes directly over its existing authenticated HTTP connection. Do not put base64 or another file source in the execute arguments.

Use kind="document" plus the exact entity_name for any of the 17 supported document owners. The local transport accepts the server-supported PDF, image, Office, ZIP and UTF-8 text formats, nonempty and at most 20,000,000 bytes. The legacy purchase-invoice kind stays PDF-only; article-image create/replace stays JPEG/PNG with a 12,000,000-byte limit. Filename hints are checked against actual bytes locally and again by the server. All uploads start inside agents; there is no upload landing page or manual file-picker flow. The transport never overrides permissions, approval, ownership or replace identity. Existing small inline-file tools retain their server-side contract.

Local files require POSIX directory-descriptor and no-follow support, available on supported macOS/Linux hosts. A platform lacking these primitives rejects --file-root explicitly; normal DeviceOAuth/STDIO remains available. The root, its ancestors and every file-path component must be real directories/files, not symbolic links. Use canonical absolute paths (for example /private/tmp instead of the macOS /tmp symlink). Parent traversal, directories, devices, FIFOs, unsupported file types and oversized files are refused.

The connector holds the original directory and file descriptors through preview/execute: replacing a pathname cannot substitute another file. Changes to the original file contents fail the hash check before transfer. Up to 32 prepared transfers are held for ten minutes, released on the next request or session exit. File bytes are not put in JSON-RPC, persisted to a staging file, or written to logs; only the filename and approved metadata reach the model.

A binary POST is attempted once, including when an HTTP 401 is returned. There is no automatic retry after a lost response. Within the same session a confirmed result can be returned again without another POST; an uncertain result requires get_upload_intent_status with the returned reference. After a connector restart or expiry the open file binding is gone: inspect the existing intent status before preparing anything again. This is not an instruction to repeat a possibly completed ERP write.

The package's real STDIO/HTTP tests prove the local transport and its guards. They are not a proof of an actual Claude Code/Codex session, the hosted backend, or a weclapp upload; those client and ERP acceptance checks remain separate.

Recovering from a broken credential file

logout removes the local credential file without validating it, so a truncated, hand-edited or wrongly-permissioned file never locks you out. It does not end the connection on the server — the device grant stays active and keeps occupying an enrollment slot until you revoke it or remove the connection in the dashboard.

revoke calls the RFC 7009 revocation endpoint. If the stored file no longer validates, it still recovers the client id, refresh token and revocation endpoint from it and revokes with those, as long as the endpoint is the canonical one on the origin the file itself names. The outcomes are:

Situation Exit Local file
Grant revoked 0 removed
File invalid, but a token was recoverable and revoked 0 removed
File unreadable, nothing revocable 2 removed — revoke in the dashboard
Revocation call failed (issuer down, network) 1 kept — use logout to remove it

After any of these, login works again.

Migrating from the connector that shipped inside the server

Until this release the command was weclapp-mcp-device, installed by the proprietary weclapp-mcp distribution, and its credentials lived in ~/.config/weclapp-mcp/device.json (%APPDATA%\weclapp-mcp\device.json on Windows). That file holds a live refresh-token family that this connector cannot revoke, and the command that could is gone.

Before or right after switching: revoke that connection in the dashboard under Connections, then delete the old directory. login prints a reminder when it finds one.

Support

There is no public issue tracker. Report defects and questions to support@wals.pro; include the connector version (walspro-ai --version) and the exact message, never the credential file.

Security properties

  • Strict origin binding: issuer, token, revocation and resource URLs must all live on the same canonical origin, on their exact canonical paths.
  • The OAuth calls refuse redirects, time out, and cap responses at 64 KiB.
  • Access tokens rotate with the refresh token; a 401 triggers exactly one refresh and one retry. A rotation whose local write fails reports that the connection is gone rather than keeping a token the server already retired.
  • Tokens are never printed, logged or passed on the command line, --verbose included. MCP SDK and httpx log records are silenced unless you ask for them, because their tracebacks quote raw upstream response bytes.
  • run fails loudly. The transport read is bounded, and a transport failure answers every unanswered request with a JSON-RPC error naming the sanitized cause and exits non-zero — it never leaves your MCP client waiting.
  • One stable public client identity per local profile; it is re-registered only after the authorization server explicitly retires it.

License

Apache-2.0. See LICENSE. Copyright 2026 Wals.pro GmbH.

The complete source of this distribution — including its test suite and the changelog — ships in the sdist (pip download --no-binary :all: walspro-ai). The repository it is developed in is private, so the package deliberately declares no Source or Changelog URL rather than a link that 404s.

Release note for maintainers

The PyPI distribution name was registered before any install instruction naming it reached a customer-facing surface. That ordering is deliberate and not optional: an unregistered name printed in a dashboard, a README or a doc is claimable by anyone, and the first person to claim it would be shipping the package customers install as their OAuth device connector. Register the name first, then merge the instruction.

Metadata

Release files for walspro-ai 0.2.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for walspro-ai 0.2.1
File Size Uploaded
walspro_ai-0.2.1.tar.gz 71.6 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for walspro-ai 0.2.1
File Interpreter ABI Platform
walspro_ai-0.2.1-py3-none-any.whl Python 3 none any Details

Total release size: 112.9 kB

Release files / walspro_ai-0.2.1.tar.gz

Download URL walspro_ai-0.2.1.tar.gz
Size 71.6 kB
Tags Source
SHA-256 checksum
How to use checksums
45c5faa73501b46df9955bf37d63f35fddea72f529396f07c8ba29731542654f
BLAKE2b-256 checksum
How to use checksums
39672b4b3c9170d5e8558405fda0b358a83184dfeca2d0696e4052664783b9f3
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 14, 2026.

Transparency log

Release files / walspro_ai-0.2.1-py3-none-any.whl

Download URL walspro_ai-0.2.1-py3-none-any.whl
Size 41.3 kB
Tags Python 3
SHA-256 checksum
How to use checksums
b593af4beb2b93ff399ad84181df1f2c8a880fd3f816e5e94bbec70e2714ac9f
BLAKE2b-256 checksum
How to use checksums
9bdb8f9b80e625da16f3801a33180cb4029baadd213bd83e7efc357c78c02acc
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 14, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.2.1 This release

2 release files

0.1.0

2 release files

0.0.1

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page