Describe the bug
When DATABASE_URI has no password (e.g. Kerberos SSO with LOGMECH=KRB5, or JWT/browser auth), TDConn.init in teradata_mcp_server/tools/td_connect.py builds the SQLAlchemy URL with an f-string that stringifies a None password into the literal 4-character string "None":
password = parsed_url.password # None when the URI carries no password
...
sqlalchemy_url = (
f"teradatasql://{user}:{password}@{self._base_host}:{self._base_port}/{self._base_db}?{main_query}"
)
# -> "teradatasql://171776:None@host:1025/db?LOGMECH=KRB5" (password is the literal "None")
The server therefore logs on with a bogus password "None", which breaks passwordless authentication. With the teradatasql 20.x driver this surfaces as a hard logon failure on Windows SSPI/Kerberos:
[Version 20.0.0.63] [Session 0] [Teradata Security] [Error 0xD0000/0xE3000259]
Error while passing an invalid handle.
... goteragss.(*sspiSecContext).gsspInitSecContext (Gssp2Sspi.go:225)
Root cause: given an explicit (non-empty) password together with LOGMECH=KRB5, the Go driver attempts an explicit-credential SSPI logon instead of using the cached Kerberos ticket, and fails. The same defect affects any path building f"teradatasql://{user}:{secret}@..." when a component is None (e.g. _validate_jwt_token).
To Reproduce
Steps to reproduce the behavior:
- On a host with a valid Kerberos TGT, set DATABASE_URI=teradata://@:1025/?logmech=KRB5 (no password).
- Start the MCP server and invoke any tool that hits the database (e.g. dba_databaseVersion).
- See the logon fail with Error 0xD0000/0xE3000259 - Error while passing an invalid handle.
Minimal driver-level repro that isolates it from the MCP server:
import teradatasql
HOST = "<host>"
# passwordless SSO -> works
teradatasql.connect(host=HOST, user="<user>", logmech="KRB5").cursor().execute("SELECT 1")
# literal "None" password (what the server builds) -> fails with the invalid-handle error
teradatasql.connect(host=HOST, user="<user>", password="None", logmech="KRB5")
# empty-string password -> works
teradatasql.connect(host=HOST, user="<user>", password="", logmech="KRB5").cursor().execute("SELECT 1")
| password value passed |
outcome |
| omitted (SSO) |
SELECT 1 OK |
| "None" (current server behaviour) |
invalid handle logon failure |
| "" (empty) |
SELECT 1 OK |
Expected behavior
When the URI has no username and/or no password, the reconstructed connection string should omit those components (or pass empty strings) rather than emitting the literal "None", so passwordless mechanisms (KRB5, JWT, browser, etc.) authenticate correctly.
Suggested fix — use SQLAlchemy's URL builder, which handles None correctly, instead of an f-string:
from sqlalchemy import URL
sqlalchemy_url = URL.create(
"teradatasql",
username=user, # None -> omitted
password=password, # None -> omitted (not "None")
host=self._base_host,
port=self._base_port,
database=self._base_db or None,
query={"LOGMECH": self._default_basic_logmech, **self._extra_uri_params},
)
(and the equivalent for the _validate_basic_credentials / _validate_jwt_token URLs).
Screenshots
N/A
Desktop (please complete the following information):
- OS: Windows 11
- teradata-mcp-server version: 0.2.5
- teradatasql: 20.0.0.63, teradatasqlalchemy: 20.0.0.9
- SQLAlchemy: 2.0.51
- Python: 3.14
- Auth: Kerberos SSO, LOGMECH=KRB5, no stored password
- Teradata server: 17.20.03.38
Smartphone (please complete the following information):
N/A
Additional context
Workaround for users (no code change): give the URI an explicit empty password by adding a colon after the username, so the f-string preserves it as empty instead of "None":
DATABASE_URI=teradata://<user>:@<host>:1025/<db>?logmech=KRB5
Verified this connects successfully via KRB5 SSO on the affected versions. Likely only manifests with the teradatasql 20.x Go driver; older C-based drivers appear to have ignored the stray password.
Describe the bug
When DATABASE_URI has no password (e.g. Kerberos SSO with LOGMECH=KRB5, or JWT/browser auth), TDConn.init in teradata_mcp_server/tools/td_connect.py builds the SQLAlchemy URL with an f-string that stringifies a None password into the literal 4-character string "None":
The server therefore logs on with a bogus password "None", which breaks passwordless authentication. With the teradatasql 20.x driver this surfaces as a hard logon failure on Windows SSPI/Kerberos:
Root cause: given an explicit (non-empty) password together with LOGMECH=KRB5, the Go driver attempts an explicit-credential SSPI logon instead of using the cached Kerberos ticket, and fails. The same defect affects any path building f"teradatasql://{user}:{secret}@..." when a component is None (e.g. _validate_jwt_token).
To Reproduce
Steps to reproduce the behavior:
Minimal driver-level repro that isolates it from the MCP server:
Expected behavior
When the URI has no username and/or no password, the reconstructed connection string should omit those components (or pass empty strings) rather than emitting the literal "None", so passwordless mechanisms (KRB5, JWT, browser, etc.) authenticate correctly.
Suggested fix — use SQLAlchemy's URL builder, which handles None correctly, instead of an f-string:
(and the equivalent for the _validate_basic_credentials / _validate_jwt_token URLs).
Screenshots
N/A
Desktop (please complete the following information):
Smartphone (please complete the following information):
N/A
Additional context
Workaround for users (no code change): give the URI an explicit empty password by adding a colon after the username, so the f-string preserves it as empty instead of "None":
DATABASE_URI=teradata://<user>:@<host>:1025/<db>?logmech=KRB5Verified this connects successfully via KRB5 SSO on the affected versions. Likely only manifests with the teradatasql 20.x Go driver; older C-based drivers appear to have ignored the stray password.