The Duplicate action you are referring to is simply defined as
<a class="dropdown-item" role="menuitem" name="copy" type="object">Duplicate</a>
-> It's the generic copy() method used all over the place to duplicate records. project.project slightly modified it though: https://github.com/odoo/odoo/blob/b0e8cb21577966108ce3885e4fbcb7314d965660/addons/project/models/project_project.py#L457
Still, this will work perfectly fine:
import xmlrpc.client
url = 'https://odoo.example.com'
db = 'example-odoo-dbname'
username = 'username'
password = 'password'
project_id = 42 # the project id to copy
# Auth
common = xmlrpc.client.ServerProxy('{}/xmlrpc/2/common'.format(url))
uid = common.authenticate(db, username, password, {})
# Copy project
models = xmlrpc.client.ServerProxy('{}/xmlrpc/2/object'.format(url))
result = models.execute_kw(db, uid, password, 'project.project', 'copy', [[project_id]])
print(result) # list of new project.project ids
In order to get the project.project object, just search/browse/read for it with the result.
See also https://www.odoo.com/documentation/18.0/de/developer/reference/external_api.html